Combine dos columnas de texto en el marco de datos de pandas

Resuelto user2866103 asked hace 11 años • 0 respuestas

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
user2866103 avatar Oct 15 '13 16:10 user2866103
Aceptado

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.

silvado avatar Oct 15 '2013 10:10 silvado

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

ingrese la descripción de la imagen aquí

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

MaxU - stand with Ukraine avatar Apr 28 '2016 10:04 MaxU - stand with Ukraine
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í

Russ avatar Sep 11 '2015 17:09 Russ

El método cat()del .strdescriptor 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.

LeoRochael avatar Mar 07 '2016 18:03 LeoRochael