pandas 三方连接多个数据框的列
我有三个CSV文件。每个文件的第一列是人的名字(字符串),而其他列则是每个人的属性。
我该怎么把这三个CSV文件“合并”在一起,创建一个新的CSV文件,让每一行都包含每个独特名字的所有属性呢?
在pandas中,join()
函数要求我使用多重索引,但我对什么是层次索引以及它和基于单一索引的合并有什么关系感到困惑。
12 个回答
21
对于一组数据框(dataframe)df_list
,你也可以这样做:
df = df_list[0]
for df_ in df_list[1:]:
df = df.merge(df_, on='join_col_name')
或者,如果这些数据框在一个生成器对象里(比如为了减少内存使用):
df = next(df_list)
for df_ in df_list:
df = df.merge(df_, on='join_col_name')
41
在 python
3.6.3 和 pandas
0.22.0 中,你可以使用 concat
函数,只要你把想要用来连接的列设置为索引就可以了。
pd.concat(
objs=(iDF.set_index('name') for iDF in (df1, df2, df3)),
axis=1,
join='inner'
).reset_index()
这里的 df1
、df2
和 df3
是按照 John Galt 的回答 中的定义来的:
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']
)
162
这是使用 join
方法的理想情况
join
方法正是为这种情况而设计的。你可以用它把任意数量的数据表(DataFrame)连接在一起。调用这个方法的数据表会根据传入的数据表的索引进行连接。要处理多个数据表,你需要把要连接的列放在索引中。
代码大概是这样的:
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
175
如果你有三个数据框,可以试试这个方法。
# 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')
645
Zero的回答其实就是在讲一个叫做reduce
的操作。如果我有很多数据框(dataframe),我会把它们放在一个列表里,就像这样(可以通过列表推导或者循环等方式生成):
dfs = [df0, df1, df2, ..., dfN]
假设这些数据框有一个共同的列,比如你例子中的name
,我会这样做:
import functools as ft
df_final = ft.reduce(lambda left, right: pd.merge(left, right, on='name'), dfs)
这样一来,你的代码就可以处理任意数量的数据框合并了。