pandas的concat函数在忽略索引时无法正常工作,无法合并列。

110
我正在尝试将数据框(类似于R的cbind()函数)进行列绑定,并且在使用pandas的concat函数时遇到了问题,因为ignore_index=True似乎不起作用。
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                    'B': ['B0', 'B1', 'B2', 'B3'],
                    'D': ['D0', 'D1', 'D2', 'D3']},
                   index=[0, 2, 3, 4])

df2 = pd.DataFrame({'A1': ['A4', 'A5', 'A6', 'A7'],
                    'C': ['C4', 'C5', 'C6', 'C7'],
                    'D2': ['D4', 'D5', 'D6', 'D7']},
                   index=[5, 6, 7, 3])
df1
#     A   B   D
# 0  A0  B0  D0
# 2  A1  B1  D1
# 3  A2  B2  D2
# 4  A3  B3  D3

df2
#    A1   C  D2
# 5  A4  C4  D4
# 6  A5  C5  D5
# 7  A6  C6  D6
# 3  A7  C7  D7

dfs = [df1, df2]
df = pd.concat(dfs, axis=1, ignore_index=True)     
print df   

结果是
     0    1    2    3    4    5    
0   A0   B0   D0  NaN  NaN  NaN  
2   A1   B1   D1  NaN  NaN  NaN    
3   A2   B2   D2   A7   C7   D7   
4   A3   B3   D3  NaN  NaN  NaN  
5  NaN  NaN  NaN   A4   C4   D4  
6  NaN  NaN  NaN   A5   C5   D5  
7  NaN  NaN  NaN   A6   C6   D6           

即使我使用重置索引
df1.reset_index()    
df2.reset_index() 

然后尝试一下
pd.concat([df1, df2], axis=1) 

它仍然产生相同的结果!
预期的结果是一个6x4的数据框,其中列A、B、D、A1、C、D2的内容是水平连接的。

1
pd.concat([df1, df2], axis=0, ignore_index=True) 这个函数是否能够得到你想要的结果?如果不行,你能具体说明一下你期望的输出是什么吗? - Alex Riley
1
不,它绑定的是行。我想要绑定列(追加)。我尝试了追加,但似乎也不起作用。 - muon
1
@ajcr,你有比较过 pd.concat([df1, df2], axis=1, ignore_index=True)pd.concat([df1, df2], axis=1) 的输出吗?第一个是否直观地模拟了cbind的功能? - cel
2
我认为 ignore_index 只会忽略你要连接的轴上的标签,所以它仍然会在索引标签上进行外部连接。我同意函数参数的名称在这里并不是最直观的。 - Alex Riley
1
是的,我从@Alex的回答中意识到了这一点...但即使ignore_index=False,我仍然得到相同的结果。 - muon
6个回答

142
如果我理解你的意思没错的话,这就是你想要做的事情。
import pandas as pd

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                    'B': ['B0', 'B1', 'B2', 'B3'],
                    'D': ['D0', 'D1', 'D2', 'D3']},
                   index=[0, 2, 3, 4])

df2 = pd.DataFrame({'A1': ['A4', 'A5', 'A6', 'A7'],
                    'C': ['C4', 'C5', 'C6', 'C7'],
                    'D2': ['D4', 'D5', 'D6', 'D7']},
                   index=[4, 5, 6 , 7])


df1.reset_index(drop=True, inplace=True)
df2.reset_index(drop=True, inplace=True)

df = pd.concat([df1, df2], axis=1) 

这是什么意思:

    A   B   D   A1  C   D2
0   A0  B0  D0  A4  C4  D4
1   A1  B1  D1  A5  C5  D5
2   A2  B2  D2  A6  C6  D6
3   A3  B3  D3  A7  C7  D7

实际上,我本来期望df = pd.concat(dfs, axis=1, ignore_index=True)会得到相同的结果。
这是jreback的精彩解释:
ignore_index=True的意思是“忽略”,也就是说不在连接轴上进行对齐。它只是按照传递的顺序将它们粘贴在一起,然后为实际索引重新分配一个范围(例如range(len(index)))。 所以,在非重叠索引上进行连接的区别(假设示例中的axis=1)是,使用ignore_index=False(默认值),您会得到索引的连接,而使用ignore_index=True则会得到一个范围。


哦,那个可以用...谢谢!有趣的是我之前在函数内部使用同样的方法来绑定数据框,而那个是正常工作的!但是在函数外面就不行了。 - muon
2
@mau,我已经更新了我的答案,现在使用 pd.reset_index()。我认为这是一种更清晰的方式。 - cel
19
如果我早点看到这个方法,我自己尝试一下的话就可以节省几个小时了 :). 谢谢... df = pd.concat( [df1.reset_index(drop=True), df2.reset_index(drop=True)], axis=1) - muon

36

在您的示例中,ignore_index选项正在工作,您只需要知道它忽略了连接轴(在您的情况下是列)。 (也许更好的名称应该是ignore_labels。)如果您希望连接忽略索引标签,则您的axis变量必须设置为0(默认值)。


谢谢!那很有帮助(还不能点赞,声望太低) - muon
1
确实,这是文档中缺失的有用解释。 - Hugo Santos Silva

25

如果你想保留左侧数据框的索引,可以使用set_index将df2的索引设置为df1:

pd.concat([df1, df2.set_index(df1.index)], axis=1)

8
同意评论,最好发布预期的输出。
这是你在寻找的吗?
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                    'B': ['B0', 'B1', 'B2', 'B3'],
                    'D': ['D0', 'D1', 'D2', 'D3']},
                   index=[0, 2, 3, 4])

df2 = pd.DataFrame({'A1': ['A4', 'A5', 'A6', 'A7'],
                    'C': ['C4', 'C5', 'C6', 'C7'],
                    'D2': ['D4', 'D5', 'D6', 'D7']},
                   index=[5, 6, 7, 3])

df1 = df1.transpose().reset_index(drop=True).transpose()
df2 = df2.transpose().reset_index(drop=True).transpose()

dfs = [df1, df2]
df = pd.concat(dfs, axis=0, ignore_index=True)

print df

    0   1   2
0  A0  B0  D0
1  A1  B1  D1
2  A2  B2  D2
3  A3  B3  D3
4  A4  C4  D4
5  A5  C5  D5
6  A6  C6  D6
7  A7  C7  D7

值得一提的是,df1.transpose().reset_index(drop=True).transpose() 或者更简洁的 df1.T.reset_index(drop=True).T 只是 pandas 中用于“删除列名”的一种惯用法。 - undefined

5
你可以使用NumPy的concatenate函数来实现这个结果。
cols = df1.columns.to_list() + df2.columns.to_list()
dfs = [df1,df2]
df = np.concatenate(dfs, axis=1)  
df = pd.DataFrame(df, columns=cols)

Out[1]: 
    A   B   D  A1   C  D2
0  A0  B0  D0  A4  C4  D4
1  A1  B1  D1  A5  C5  D5
2  A2  B2  D2  A6  C6  D6
3  A3  B3  D3  A7  C7  D7

1
由于某种原因,ignore_index=True在我的情况下没有起作用。 我想保留第一个数据集的索引并忽略第二个索引。这对我有用:
X_train = pd.concat([train_sp, X_train.reset_index(drop=True, inplace=True)], axis=1)

inplace=True?那里不应该有,它会使其返回None - wjandrea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接