Python pandas三向连接列上的多个数据帧
我有3个CSV文件。每个数据帧的第一列都是人名(字符串),而每个数据帧中的所有其他列都是该人名的属性 如何将所有三个CSV文档“连接”在一起,以创建一个CSV,其中每一行都具有个人字符串名称的每个唯一值的所有属性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,
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@ps0604df1.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
已替换为Soimport 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.concat
pd.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)