大pandasjoin列上的多个数据框

我有3个CSV文件。 每个人都有第一列作为(string)人名,而每个数据框中的所有其他列都是该人的属性。

如何将所有三个CSV文档“join”在一起,以创build一个单一的CSV文件,每行都具有该人员string名称的每个唯一值的所有属性?

pandas中的join()函数指定我需要一个多重索引,但是我对于根据单个索引进行连接时分层索引scheme的作用感到困惑。

如果你有3个数据框,你可以试试这个

 # 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') 

或者,正如cwharland所说的那样

 df1.merge(df2,on='name').merge(df3,on='name') 

假定import:

 import pandas as pd 

约翰·高尔特的答案基本上是一个reduce操作。 如果我有一些以上的数据框,我会把它们放在这样的列表中(通过列表parsing或循环或什么):

 dfs = [df0, df1, df2, dfN] 

假设他们有一些共同的专栏,如你的例子中的name ,我会做以下几点:

 df_final = reduce(lambda left,right: pd.merge(left,right,on='name'), dfs) 

这样,你的代码应该可以处理你想合并的任何数量的dataframe。

编辑2016年8月1日 :对于那些使用Python 3: reduce已被移入functools 。 所以要使用这个函数,你首先需要导入那个模块。

对于dataframe列表df_list也可以按如下方式完成:

 df = df_list[0] for df_ in df_list[1:]: df = df.merge(df_, on='join_col_name') 

或者dataframe是否在生成器对象中(例如,为了减less内存消耗):

 df = next(df_list) for df_ in df_list: df = df.merge(df_, on='join_col_name') 

这是一种合并数据框字典的同时保持列名与字典同步的方法。 如果需要,它也填写缺失的值:

这是合并dataframe的字典的function

 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) 

好吧,让我们生成数据并testing这个:

 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) 

一个不需要multiindex来执行连接操作。 只需要正确设置要执行连接操作的索引列(例如,命令df.set_index('Name')

join操作默认在索引上执行。 在你的情况下,你只需要指定Name列对应于你的索引。 下面是一个例子

一个教程可能是有用的。

 # 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') 

这是join方法的理想情况

join方法正是针对这些types的情况而构build的。 你可以join任意数量的dataframe。 调用的DataFrame与传递的DataFrame的集合的索引连接。 要使用多个DataFrame,您必须将连接列放入索引中。

代码看起来像这样:

 filenames = ['fn1', 'fn2', 'fn3', 'fn4',....] dfs = [pd.read_csv(filename, index_col=index_col) for filename in filenames)] dfs[0].join(dfs[1:]) 

用@零的数据,你可以这样做:

 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