Combine dos columnas de texto en el marco de datos de pandas
Tengo un marco de datos que se parece
Year quarter
2000 q2
2001 q3
¿Cómo agrego una nueva columna combinando estas columnas para obtener el siguiente marco de datos?
Year quarter period
2000 q2 2000q2
2001 q3 2001q3
Si ambas columnas son cadenas, puedes concatenarlas directamente:
df["period"] = df["Year"] + df["quarter"]
Si una (o ambas) columnas no están escritas como cadena, primero debe convertirlas,
df["period"] = df["Year"].astype(str) + df["quarter"]
¡Cuidado con los NaN al hacer esto!
Si necesita unir varias columnas de cadena, puede usar agg
:
df['period'] = df[['Year', 'quarter', ...]].agg('-'.join, axis=1)
Donde "-" es el separador.
Pequeños conjuntos de datos (<150 filas)
[''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
o un poco más lento pero más compacto:
df.Year.str.cat(df.quarter)
Conjuntos de datos más grandes (> 150 filas)
df['Year'].astype(str) + df['quarter']
ACTUALIZACIÓN: Gráfico de tiempo Pandas 0.23.4
Probémoslo en 200.000 filas DF:
In [250]: df
Out[250]:
Year quarter
0 2014 q1
1 2015 q2
In [251]: df = pd.concat([df] * 10**5)
In [252]: df.shape
Out[252]: (200000, 2)
ACTUALIZACIÓN: nuevos tiempos usando Pandas 0.19.0
Temporización sin optimización de CPU/GPU (ordenadas de más rápida a más lenta):
In [107]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 131 ms per loop
In [106]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 161 ms per loop
In [108]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 189 ms per loop
In [109]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 567 ms per loop
In [110]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 584 ms per loop
In [111]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 24.7 s per loop
Sincronización utilizando la optimización de CPU/GPU:
In [113]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 53.3 ms per loop
In [114]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 65.5 ms per loop
In [115]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 79.9 ms per loop
In [116]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop
In [117]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop
In [118]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 9.38 s per loop
Contribución de respuesta de @ anton-vbr
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['period'] = df[['Year', 'quarter']].apply(lambda x: ''.join(x), axis=1)
Produce este marco de datos
Year quarter period
0 2014 q1 2014q1
1 2015 q2 2015q2
Este método se generaliza a un número arbitrario de columnas de cadena reemplazándolas df[['Year', 'quarter']]
con cualquier segmento de columna de su marco de datos, por ejemplo df.iloc[:,0:2].apply(lambda x: ''.join(x), axis=1)
.
Puede consultar más información sobre el método apply() aquí
El método cat()
del .str
descriptor de acceso funciona muy bien para esto:
>>> import pandas as pd
>>> df = pd.DataFrame([["2014", "q1"],
... ["2015", "q3"]],
... columns=('Year', 'Quarter'))
>>> print(df)
Year Quarter
0 2014 q1
1 2015 q3
>>> df['Period'] = df.Year.str.cat(df.Quarter)
>>> print(df)
Year Quarter Period
0 2014 q1 2014q1
1 2015 q3 2015q3
cat()
incluso le permite agregar un separador, por lo que, por ejemplo, supongamos que solo tiene números enteros para el año y el período, puede hacer esto:
>>> import pandas as pd
>>> df = pd.DataFrame([[2014, 1],
... [2015, 3]],
... columns=('Year', 'Quarter'))
>>> print(df)
Year Quarter
0 2014 1
1 2015 3
>>> df['Period'] = df.Year.astype(str).str.cat(df.Quarter.astype(str), sep='q')
>>> print(df)
Year Quarter Period
0 2014 1 2014q1
1 2015 3 2015q3
Unir varias columnas es solo cuestión de pasar una lista de series o un marco de datos que contenga todas menos la primera columna como parámetro para str.cat()
invocar en la primera columna (Serie):
>>> df = pd.DataFrame(
... [['USA', 'Nevada', 'Las Vegas'],
... ['Brazil', 'Pernambuco', 'Recife']],
... columns=['Country', 'State', 'City'],
... )
>>> df['AllTogether'] = df['Country'].str.cat(df[['State', 'City']], sep=' - ')
>>> print(df)
Country State City AllTogether
0 USA Nevada Las Vegas USA - Nevada - Las Vegas
1 Brazil Pernambuco Recife Brazil - Pernambuco - Recife
Tenga en cuenta que si su marco de datos/serie de pandas tiene valores nulos, debe incluir el parámetro na_rep para reemplazar los valores de NaN con una cadena; de lo contrario, la columna combinada tendrá el valor predeterminado NaN.