我有3个CSV文件。每个数据框架的第一列都是人的(字符串)名,而每个数据框架中的所有其他列都是人的属性。
我如何将所有三个CSV文档“联接”在一起,以创建一个单一的CSV,其中每行都具有人的字符串名称的每个唯一值的所有属性?
pandas中的join()函数指定我需要一个多索引,但我对分层索引方案与基于单个索引进行连接有什么关系感到困惑。
我有3个CSV文件。每个数据框架的第一列都是人的(字符串)名,而每个数据框架中的所有其他列都是人的属性。
我如何将所有三个CSV文档“联接”在一起,以创建一个单一的CSV,其中每行都具有人的字符串名称的每个唯一值的所有属性?
pandas中的join()函数指定我需要一个多索引,但我对分层索引方案与基于单个索引进行连接有什么关系感到困惑。
当前回答
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],
['d', 14, 16]]
),
columns=['name', 'attr21', 'attr22']
)
df3 = pd.DataFrame(np.array([
['a', 15, 49],
['c', 4, 36],
['d', 14, 9]]),
columns=['name', 'attr31', 'attr32']
)
df4 = pd.DataFrame(np.array([
['a', 15, 49],
['c', 4, 36],
['c', 14, 9]]),
columns=['name', 'attr41', 'attr42']
)
加入列表数据框架的三种方法
pandas.concat
dfs = [df1, df2, df3]
dfs = [df.set_index('name') for df in dfs]
# cant not run if index not unique
dfs = pd.concat(dfs, join='outer', axis = 1)
functools.reduce
dfs = [df1, df2, df3, df4]
# still run with index not unique
import functools as ft
df_final = ft.reduce(lambda left, right: pd.merge(left, right, on='name', how = 'outer'), dfs)
加入
# cant not run if index not unique
dfs = [df1, df2, df3]
dfs = [df.set_index('name') for df in dfs]
dfs[0].join(dfs[1:], how = 'outer')
其他回答
熊猫文档中还有另一个解决方案(我在这里没有看到),
使用.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,只要你将你想要用于连接的列设置为index:
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']
)
0的答案基本上是一个约简运算。如果我有很多数据框架,我会把它们放在一个这样的列表中(通过列表推导或循环或诸如此类的东西生成):
dfs = [df0, df1, df2, ..., dfN]
假设他们有一个共同的列,就像你的例子中的name一样,我会做以下事情:
import functools as ft
df_final = ft.reduce(lambda left, right: pd.merge(left, right, on='name'), dfs)
这样,您的代码就可以处理您想合并的任何数量的数据框架。
对于一个数据帧列表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')
简单的解决方案:
如果列名相似:
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'})