Python pandas三向连接列上的多个数据帧

Python pandas三向连接列上的多个数据帧,python,pandas,join,merge,Python,Pandas,Join,Merge,我有3个CSV文件。每个数据帧的第一列都是人名(字符串),而每个数据帧中的所有其他列都是该人名的属性 如何将所有三个CSV文档“连接”在一起,以创建一个CSV,其中每一行都具有个人字符串名称的每个唯一值的所有属性 pandas中的join()函数指定我需要一个多索引,但我不清楚分层索引方案与基于单个索引进行连接有什么关系 如果您有3个数据帧,可以尝试此方法 # Merge multiple dataframes df1 = pd.DataFrame(np.array([ ['a', 5,

我有3个CSV文件。每个数据帧的第一列都是人名(字符串),而每个数据帧中的所有其他列都是该人名的属性

如何将所有三个CSV文档“连接”在一起,以创建一个CSV,其中每一行都具有个人字符串名称的每个唯一值的所有属性


pandas中的
join()
函数指定我需要一个多索引,但我不清楚分层索引方案与基于单个索引进行连接有什么关系

如果您有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')
或者,正如哈兰德所提到的

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

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

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

A可能有用

# 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 have 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')
假定进口:

import pandas as pd
基本上是一个
reduce
操作。如果我有多个数据帧,我会将它们放在这样的列表中(通过列表理解或循环或诸如此类的方式生成):

假设它们有一些公共列,如示例中的
name
,我将执行以下操作:

df_final = reduce(lambda left,right: pd.merge(left,right,on='name'), dfs)
这样,您的代码就可以处理任意数量的要合并的数据帧

编辑:2016年8月1日:对于使用Python 3的用户:
reduce
已移至
functools
。因此,要使用此函数,首先需要导入该模块:

from functools import reduce

对于数据帧列表,也可以按如下方式执行此操作:

df = df_list[0]
for df_ in df_list[1:]:
    df = df.merge(df_, on='join_col_name')
或者,如果数据帧位于生成器对象中(例如,为了减少内存消耗):


下面是一种合并数据帧字典的方法,同时保持列名与字典同步。如果需要,它还会填充缺少的值:

这是合并数据帧的功能 好的,让我们生成数据并测试: 这是
join
方法的理想情况
join
方法正是针对这些类型的情况构建的。您可以将任意数量的数据帧与它连接在一起。调用的数据帧与传递的数据帧集合的索引联接。要使用多个数据帧,必须将连接列放入索引中

代码如下所示:

filenames = ['fn1', 'fn2', 'fn3', 'fn4',....]
dfs = [pd.read_csv(filename, index_col=index_col) for filename in filenames)]
dfs[0].join(dfs[1:])
使用@zero的数据,您可以执行以下操作:

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

还有另一个解决方案(我在这里没有看到)

使用
.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
ignore_index=True
用于忽略附加数据帧的索引,用源数据帧中可用的下一个索引替换它


如果有不同的列名,则将引入
Nan

python
3.6.3和
pandas
0.22.0中,您还可以使用
concat
,只要将要用于连接的列设置为索引

pd.concat(
    (iDF.set_index('name') for iDF in [df1, df2, df3]),
    axis=1, join='inner'
).reset_index()
其中
df1
df2
df3
的定义如中所示


简单解决方案:

如果列名相似:

 df1.merge(df2,on='col_name').merge(df3,on='col_name')
如果列名不同:

df1.merge(df2,left_on='col_name1', right_on='col_name2').merge(df3,left_on='col_name1', right_on='col_name3').drop(columns=['col_name2', 'col_name3']).rename(columns={'col_name1':'col_name'})

我使用
reduce
对接受的答案进行了调整,以便在不同的
后缀
参数上对多个数据帧执行操作,我想它也可以扩展到不同的
参数上

from functools import reduce 

dfs_with_suffixes = [(df2,suffix2), (df3,suffix3), 
                     (df4,suffix4)]

merge_one = lambda x,y,sfx:pd.merge(x,y,on=['col1','col2'..], suffixes=sfx)

merged = reduce(lambda left,right:merge_one(left,*right), dfs_with_suffixes, df1)

你不需要多重索引。它在连接文档中声明,当传递多个列进行连接时,您没有多索引,然后它将处理该问题。在我的试验中,
df1.join([df2,df3],on=[df2_col1,df3_col1])
不起作用。您需要像给出的答案那样将它们链接在一起。合并df1和df2然后将结果与df3合并为更清晰的外观您可以链接它们
df1.Merge(df2,on='name')。Merge(df3,on='name')
如果要连接的字段的名称不同,该解决方案将如何工作?例如,在三个数据帧中,我可以有
name1
name2
name3
respectively@ps0604
df1.merge(df2,left_on='name1',right_on='name2')。merge(df3,left_on='name1',right_on='name3')。drop(columns=['name2','name3'])。rename(columns={'name1':'name'})
以及如何使用索引执行此操作。如果“name”是索引而不是列名,则似乎不起作用。我只是尝试使用它,但失败了,因为
reduce
已替换为So
import functools。reduce(……)
如果要连接的字段的名称不同,该解决方案将如何工作?例如,在三个数据帧中,我可以分别调用
name1
name2
name3
。这是否意味着我们可以调用
n-1
合并函数?我想在这种情况下,数据帧的数量很小并不重要,但我想知道是否有一个更具可伸缩性的解决方案。这对我的
df
s(具有列多索引)不太有效(它将“on”作为一个列注入,这对第一次合并有效,但随后的合并失败),相反,我让它使用:
df=reduce(lambda left,right:left.join(right,how='outer',on='Date'),dfs)
+1到ps0604。如果联接列不同,该怎么办?如果连接列不同,我们是否应该使用pd.merge?thanksit的语义,对于使用“join”一词来表示将两个数据帧放在一起的人来说。(不必像SQL join操作那样)将所有dfs连接到一个空数据帧也可以工作:
pd.dataframe().join(dfs,how=“outer”)
。在某些情况下,这会更干净。这是一个不错的建议,现在已经被合并到(请参阅合并多个数据帧部分)。值得注意的是,如果您的连接键是唯一的,请使用
pd.concatpd.concat(
    (iDF.set_index('name') for iDF in [df1, df2, df3]),
    axis=1, join='inner'
).reset_index()
import pandas as pd
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']
)
 df1.merge(df2,on='col_name').merge(df3,on='col_name')
df1.merge(df2,left_on='col_name1', right_on='col_name2').merge(df3,left_on='col_name1', right_on='col_name3').drop(columns=['col_name2', 'col_name3']).rename(columns={'col_name1':'col_name'})
from functools import reduce 

dfs_with_suffixes = [(df2,suffix2), (df3,suffix3), 
                     (df4,suffix4)]

merge_one = lambda x,y,sfx:pd.merge(x,y,on=['col1','col2'..], suffixes=sfx)

merged = reduce(lambda left,right:merge_one(left,*right), dfs_with_suffixes, df1)