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.
Respuestas:
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ó RafaelCdf.year.astype(int)
)Editar: tenga en cuenta también el comentario de Anderson Zhu: en caso de que tenga
None
o falten valores en uno de sus marcos de datos, debe usar enInt64
lugar deint
. Vea la referencia aquí .fuente
df.year.astype(int)
?Int64
lugar deint
. Vea la referencia aquí .Descubrí que mis dfs tenían el mismo tipo de columna (
str
) pero el cambio dejoin
amerge
resolvió el problema.fuente
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í.df1.join(df2)
siempre se fusiona a través del índice dedf2
mientras quedf1.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 ...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.
fuente
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)
ydf.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
df['Qty'].astype(str) df.dtypes
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
Ahora la tarea
df['Qty'] = df['Qty'].astype(str) df.dtypes
fuente
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.
fuente
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.
fuente
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"]
fuente