Intentando fusionar 2 marcos de datos pero obteniendo ValueError

84

Estos son mis dos marcos de datos guardados en dos variables:

> print(df.head())
>
          club_name  tr_jan  tr_dec  year
    0  ADO Den Haag    1368    1422  2010
    1  ADO Den Haag    1455    1477  2011
    2  ADO Den Haag    1461    1443  2012
    3  ADO Den Haag    1437    1383  2013
    4  ADO Den Haag    1386    1422  2014
> print(rankingdf.head())
>
           club_name  ranking  year
    0    ADO Den Haag    12    2010
    1    ADO Den Haag    13    2011
    2    ADO Den Haag    11    2012
    3    ADO Den Haag    14    2013
    4    ADO Den Haag    17    2014

Estoy tratando de fusionar estos dos usando este código:

new_df = df.merge(ranking_df, on=['club_name', 'year'], how='left')

Se agrega cómo = 'izquierda' porque tengo menos puntos de datos en mi ranking_df que en mi df estándar.

El comportamiento esperado es como tal:

> print(new_df.head()) 
> 

      club_name  tr_jan  tr_dec  year    ranking
0  ADO Den Haag    1368    1422  2010    12
1  ADO Den Haag    1455    1477  2011    13
2  ADO Den Haag    1461    1443  2012    11
3  ADO Den Haag    1437    1383  2013    14
4  ADO Den Haag    1386    1422  2014    17

Pero me sale este error:

ValueError: está intentando fusionar el objeto y las columnas int64. Si desea continuar, debe usar pd.concat

Pero no deseo usar concat ya que quiero fusionar los árboles, no solo agregarlos.

Otro comportamiento que me resulta extraño es que mi código funciona si guardo el primer df en .csv y luego cargo ese .csv en un marco de datos.

El código para eso:

df = pd.DataFrame(data_points, columns=['club_name', 'tr_jan', 'tr_dec', 'year'])
df.to_csv('preliminary.csv')

df = pd.read_csv('preliminary.csv', index_col=0)

ranking_df = pd.DataFrame(rankings, columns=['club_name', 'ranking', 'year'])

new_df = df.merge(ranking_df, on=['club_name', 'year'], how='left')

Creo que tiene que ver con el parámetro index_col = 0. Pero no tengo idea de arreglarlo sin tener que guardarlo, no importa mucho pero es una molestia tener que hacer eso.

PEREZje
fuente
Obtuve el mismo error cuando utilicé unir en lugar de unir.
Modem Rakesh goud

Respuestas:

115

En uno de sus marcos de datos, el año es una cadena y el otro es un int64, puede convertirlo primero y luego unirse (por ejemplo, df['year']=df['year'].astype(int)o como sugirió RafaelC df.year.astype(int))

Editar: tenga en cuenta también el comentario de Anderson Zhu: en caso de que tenga Noneo falten valores en uno de sus marcos de datos, debe usar en Int64lugar de int. Vea la referencia aquí .

Arnon Rotem-Gal-Oz
fuente
Gracias funcionó. Un poco extraño ya que guardaba todos los años como ints.
PEREZje
13
¿por qué no df.year.astype(int)?
rafaelc
Finalmente lo arreglé de otra manera, simplemente guardé todas las variables del año en el marco de datos como números enteros. Nunca pensé que fueran cuerdas.
PEREZje
@RafaelC eso es probablemente mejor
Arnon Rotem-Gal-Oz
2
En caso de que tenga Ninguno o valores faltantes en uno de sus marcos de datos, debe usar en Int64lugar de int. Vea la referencia aquí .
Anderson Zhu
42

Descubrí que mis dfs tenían el mismo tipo de columna ( str) pero el cambio de joina mergeresolvió el problema.

Alex Moore-Niemi
fuente
7
Igual que aquí. Si alguien sabe por qué, escriba a continuación :)
raummensch
Mismo. Muy extraño de hecho, mi única suposición es que incluso si todo es de tipo object, al hacer la combinación, los pandas intentan evaluar los tipos de datos una vez más implícitamente ... Pero la combinación también lo resolvió para mí.
Paso
6
@raummensch y @ 15Step, tuve el mismo problema. La razón por la que la combinación funciona en cadenas pero la combinación no se puede encontrar en la respuesta de @MatthiasFripp aquí: enlace . Básicamente, df1.join(df2)siempre se fusiona a través del índice de df2mientras que df1.merge(df2)se fusionará en la columna. Básicamente, estábamos tratando de fusionar en función de una cadena y un número entero, aunque ambas columnas eran cadenas ...
Nicko
3

Sucede cuando las columnas comunes en ambas tablas son de diferentes tipos de datos.

Ejemplo: en la tabla1, tiene la fecha como cadena, mientras que en la tabla2 tiene la fecha como fecha y hora. por lo que antes de fusionar, necesitamos cambiar la fecha al tipo de datos común.

Ashish Anand
fuente
2

La respuesta de @Arnon Rotem-Gal-Oz es correcta en su mayor parte. Pero me gustaría señalar la diferencia entre df['year']=df['year'].astype(int)y df.year.astype(int). df.year.astype(int)devuelve una vista del marco de datos y no cambia explícitamente el tipo, al menos en pandas 0.24.2. df['year']=df['year'].astype(int)cambie explícitamente el tipo porque es una asignación. Yo diría que esta es la forma más segura de cambiar permanentemente el tipo d de una columna.

Ejemplo:

df = pd.DataFrame({'Weed': ['green crack', 'northern lights', 'girl scout cookies'], 'Qty':[10,15,3]}) df.dtypes

Objeto de malezas, Cant. Int64

df['Qty'].astype(str) df.dtypes

Objeto de malezas, Cant. Int64

Incluso establecer el argumento en lugar en True no ayuda a veces. Aunque no sé por qué sucede esto. En la mayoría de los casos, inplace = True equivale a una asignación explícita.

df['Qty'].astype(str, inplace = True) df.dtypes

Objeto de malezas, Cant. Int64

Ahora la tarea

df['Qty'] = df['Qty'].astype(str) df.dtypes

Objeto de malezas, objeto de cantidad

escha
fuente
1

Adicional: cuando guarda df en formato .csv, la fecha y hora (año en este caso específico) se guarda como objeto, por lo que debe convertirlo en entero (año en este caso específico) cuando realice la fusión. Es por eso que cuando carga ambos df desde archivos csv, puede fusionar fácilmente, mientras que el error anterior aparecerá si un df se carga desde archivos csv y el otro es de un df existente. Esto es algo molesto, pero tiene una solución fácil si se tiene en cuenta.

CathyQian
fuente
0

esta sencilla solución funciona para mí

    final = pd.concat([df, rankingdf], axis=1, sort=False)

pero es posible que primero deba soltar alguna columna duplicada.

Ega Dharmawan
fuente
0

Al principio, compruebe el tipo de columnas que desea fusionar. Verá que uno de ellos es una cadena donde el otro está int. Luego conviértalo a int como el siguiente código:

df["something"] = df["something"].astype(int)

merged = df.merge[df1, on="something"]
Erol Erdogan
fuente