python - seleccionar - pandas uniendo mĂșltiples dataframes en columnas
seleccionar columnas pandas python (7)
Esta es una situación ideal para el método de join
El método de join
está construido exactamente para este tipo de situaciones. Puede unir cualquier número de DataFrames junto con él. El DataFrame llamante se une con el índice de la colección de DataFrames pasados. Para trabajar con múltiples DataFrames, debe colocar las columnas de unión en el índice.
El código se vería así:
filenames = [''fn1'', ''fn2'', ''fn3'', ''fn4'',....]
dfs = [pd.read_csv(filename, index_col=index_col) for filename in filenames)]
dfs[0].join(dfs[1:])
Con los datos de @ zero, podrías hacer esto:
df1 = pd.DataFrame(np.array([
[''a'', 5, 9],
[''b'', 4, 61],
[''c'', 24, 9]]),
columns=[''name'', ''attr11'', ''attr12''])
df2 = pd.DataFrame(np.array([
[''a'', 5, 19],
[''b'', 14, 16],
[''c'', 4, 9]]),
columns=[''name'', ''attr21'', ''attr22''])
df3 = pd.DataFrame(np.array([
[''a'', 15, 49],
[''b'', 4, 36],
[''c'', 14, 9]]),
columns=[''name'', ''attr31'', ''attr32''])
dfs = [df1, df2, df3]
dfs = [df.set_index(''name'') for df in dfs]
dfs[0].join(dfs[1:])
attr11 attr12 attr21 attr22 attr31 attr32
name
a 5 9 5 19 15 49
b 4 61 14 16 4 36
c 24 9 4 9 14 9
Tengo 3 archivos CSV. Cada uno tiene la primera columna como los nombres de las personas (cadena), mientras que todas las otras columnas en cada marco de datos son atributos de esa persona.
¿Cómo puedo "unir" los tres documentos CSV para crear un CSV único con cada fila con todos los atributos para cada valor único del nombre de cadena de la persona?
La función join()
en pandas especifica que necesito un multiindex, pero estoy confundido acerca de qué tiene que ver un esquema de indexación jerárquico al hacer una unión basada en un solo índice.
Aquí hay un método para combinar un diccionario de marcos de datos mientras se mantienen los nombres de las columnas sincronizados con el diccionario. También completa los valores faltantes si es necesario:
Esta es la función para fusionar un dict de marcos de datos
def MergeDfDict(dfDict, onCols, how=''outer'', naFill=None):
keys = dfDict.keys()
for i in range(len(keys)):
key = keys[i]
df0 = dfDict[key]
cols = list(df0.columns)
valueCols = list(filter(lambda x: x not in (onCols), cols))
df0 = df0[onCols + valueCols]
df0.columns = onCols + [(s + ''_'' + key) for s in valueCols]
if (i == 0):
outDf = df0
else:
outDf = pd.merge(outDf, df0, how=how, on=onCols)
if (naFill != None):
outDf = outDf.fillna(naFill)
return(outDf)
OK, permite generar datos y probar esto:
def GenDf(size):
df = pd.DataFrame({''categ1'':np.random.choice(a=[''a'', ''b'', ''c'', ''d'', ''e''], size=size, replace=True),
''categ2'':np.random.choice(a=[''A'', ''B''], size=size, replace=True),
''col1'':np.random.uniform(low=0.0, high=100.0, size=size),
''col2'':np.random.uniform(low=0.0, high=100.0, size=size)
})
df = df.sort_values([''categ2'', ''categ1'', ''col1'', ''col2''])
return(df)
size = 5
dfDict = {''US'':GenDf(size), ''IN'':GenDf(size), ''GER'':GenDf(size)}
MergeDfDict(dfDict=dfDict, onCols=[''categ1'', ''categ2''], how=''outer'', naFill=0)
Esto también se puede hacer de la siguiente manera para obtener una lista de marcos de datos df_list
:
df = df_list[0]
for df_ in df_list[1:]:
df = df.merge(df_, on=''join_col_name'')
o si los marcos de datos están en un objeto generador (por ejemplo, para reducir el consumo de memoria):
df = next(df_list)
for df_ in df_list:
df = df.merge(df_, on=''join_col_name'')
Hay otra solución de la documentación de los pandas (que no veo aquí),
usando el .append
>>> df = pd.DataFrame([[1, 2], [3, 4]], columns=list(''AB''))
A B
0 1 2
1 3 4
>>> df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list(''AB''))
A B
0 5 6
1 7 8
>>> df.append(df2, ignore_index=True)
A B
0 1 2
1 3 4
2 5 6
3 7 8
El ignore_index=True
se usa para ignorar el índice del dataframe adjunto, reemplazándolo con el siguiente índice disponible en el de origen.
Si hay diferentes nombres de columna, Nan
será presentado.
Importaciones supuestas:
import pandas as pd
La respuesta de John Galt es básicamente una operación de reduce
. Si tengo más de un puñado de marcos de datos, los pondría en una lista como esta (generada a través de comprensiones de listas o bucles o lo que sea):
dfs = [df0, df1, df2, dfN]
Suponiendo que tengan alguna columna común, como el name
en su ejemplo, haría lo siguiente:
df_final = reduce(lambda left,right: pd.merge(left,right,on=''name''), dfs)
De esta forma, su código debería funcionar con la cantidad de marcos de datos que desee fusionar.
Editar 1 de agosto de 2016 : para aquellos que usan Python 3: reduce
se ha movido a functools
. Entonces, para usar esta función, primero deberá importar ese módulo:
from functools import reduce
Puedes intentar esto si tienes 3 marcos de datos
# Merge multiple dataframes
df1 = pd.DataFrame(np.array([
[''a'', 5, 9],
[''b'', 4, 61],
[''c'', 24, 9]]),
columns=[''name'', ''attr11'', ''attr12''])
df2 = pd.DataFrame(np.array([
[''a'', 5, 19],
[''b'', 14, 16],
[''c'', 4, 9]]),
columns=[''name'', ''attr21'', ''attr22''])
df3 = pd.DataFrame(np.array([
[''a'', 15, 49],
[''b'', 4, 36],
[''c'', 14, 9]]),
columns=[''name'', ''attr31'', ''attr32''])
pd.merge(pd.merge(df1,df2,on=''name''),df3,on=''name'')
alternativamente, como lo menciona cwharland
df1.merge(df2,on=''name'').merge(df3,on=''name'')
Uno no necesita un multiindex para realizar operaciones de join . Uno solo necesita establecer correctamente la columna de índice en la que realizar las operaciones de unión (que ordenan df.set_index(''Name'')
por ejemplo)
La operación de join
se realiza de forma predeterminada en el índice. En su caso, solo tiene que especificar que la columna Name
corresponde a su índice. A continuación hay un ejemplo
Un tutorial puede ser útil.
# Simple example where dataframes index are the name on which to perform the join operations
import pandas as pd
import numpy as np
name = [''Sophia'' ,''Emma'' ,''Isabella'' ,''Olivia'' ,''Ava'' ,''Emily'' ,''Abigail'' ,''Mia'']
df1 = pd.DataFrame(np.random.randn(8, 3), columns=[''A'',''B'',''C''], index=name)
df2 = pd.DataFrame(np.random.randn(8, 1), columns=[''D''], index=name)
df3 = pd.DataFrame(np.random.randn(8, 2), columns=[''E'',''F''], index=name)
df = df1.join(df2)
df = df.join(df3)
# If you a ''Name'' column that is not the index of your dataframe, one can set this column to be the index
# 1) Create a column ''Name'' based on the previous index
df1[''Name'']=df1.index
# 1) Select the index from column ''Name''
df1=df1.set_index(''Name'')
# If indexes are different, one may have to play with parameter how
gf1 = pd.DataFrame(np.random.randn(8, 3), columns=[''A'',''B'',''C''], index=range(8))
gf2 = pd.DataFrame(np.random.randn(8, 1), columns=[''D''], index=range(2,10))
gf3 = pd.DataFrame(np.random.randn(8, 2), columns=[''E'',''F''], index=range(4,12))
gf = gf1.join(gf2, how=''outer'')
gf = gf.join(gf3, how=''outer'')