从一个DataFrame复制一列到另一个DataFrame会导致NaN值吗?

78
这个问题已经被问了很多次,而且似乎对其他人有效,但是当我从另一个DataFrame(df1和df2长度相同)复制一列时,我得到了NaN值。

df1

        date     hour      var1
a   2017-05-01  00:00:00   456585
b   2017-05-01  01:00:00   899875
c   2017-05-01  02:00:00   569566
d   2017-05-01  03:00:00   458756
e   2017-05-01  04:00:00   231458
f   2017-05-01  05:00:00   986545

df2

      MyVar1     MyVar2 
 0  6169.719338 3688.045368
 1  5861.148007 3152.238704
 2  5797.053347 2700.469871
 3  5779.102340 2730.471948
 4  6708.219647 3181.298291
 5  8550.380343 3793.580394

我需要在我的df2中像这样

       MyVar1    MyVar2        date        hour
 0  6169.719338 3688.045368  2017-05-01  00:00:00
 1  5861.148007 3152.238704  2017-05-01  01:00:00
 2  5797.053347 2700.469871  2017-05-01  02:00:00
 3  5779.102340 2730.471948  2017-05-01  03:00:00
 4  6708.219647 3181.298291  2017-05-01  04:00:00
 5  8550.380343 3793.580394  2017-05-01  05:00:00

我尝试了以下内容,
df2['date'] = df1['date']
df2['hour'] = df1['hour']

type(df1)
>> pandas.core.frame.DataFrame

type(df2)
>> pandas.core.frame.DataFrame

我得到了以下内容,
       MyVar1    MyVar2      date       hour
 0  6169.719338 3688.045368  NaN        NaN
 1  5861.148007 3152.238704  NaN        NaN
 2  5797.053347 2700.469871  NaN        NaN

为什么会发生这种情况?还有另一篇post讨论了merge,但我只需要复制它。任何帮助都将不胜感激。

3个回答

86

罪魁祸首是无法对齐的索引

您的数据框的索引不同(相应地,每列的索引也不同),因此在尝试将一个数据框的列赋值给另一个数据框时,pandas会尝试对齐索引,但由于无法对齐,会插入NaN值。

请看以下示例以理解其含义:

# Setup
A = pd.DataFrame(index=['a', 'b', 'c']) 
B = pd.DataFrame(index=['b', 'c', 'd', 'f'])                                  
C = pd.DataFrame(index=[1, 2, 3])

# Example of alignable indexes - A & B (complete or partial overlap of indexes)
A.index B.index
      a        
      b       b   (overlap)
      c       c   (overlap)
              d
              f

# Example of unalignable indexes - A & C (no overlap at all)
A.index C.index
      a        
      b        
      c        
              1
              2
              3

当两个DataFrame之间没有重叠时,pandas无法将任何一个值匹配到结果中,因此输出结果是一个充满NaN值的列。
如果你正在使用IPython笔记本进行工作,你可以使用以下方法验证这确实是根本原因。
df1.index.equals(df2.index)
# False
df1.index.intersection(df2.index).empty
# True

你可以使用以下任何解决方案来解决这个问题。
解决方案1:分配底层的NumPy数组(绕过pandas索引对齐)
只有当两个DataFrame的长度匹配(即具有相同的行数)时,此解决方案才有效。
df2['date'] = df1['date'].to_numpy()

# (In pandas < 0.24, do df2['date'] = df1['date'].values )

为了轻松地分配多个列,请使用以下方法:
df2[['date', 'hour']] = df1[['date', 'hour']].to_numpy()

解决方案2:重置两个DataFrame的索引
当两个DataFrame的长度不同时使用。如果您一开始并不打算使用不同的索引,或者您并不特别关心保留索引,这也可能是首选方法。
# Optional, if you want a RangeIndex => [0, 1, 2, ...]
# df1.index = pd.RangeIndex(len(df))
# Homogenize the index values,
df2.index = df1.index
# Assign the columns.
df2[['date', 'hour']] = df1[['date', 'hour']]

如果你想保留现有的索引,但作为一列,你可以使用reset_index()

@i.n.n.m 可能是您的索引出了问题。尝试添加 ignore_index=True?否则,先重置两个索引,然后再进行连接。 - cs95
2
@i.n.n.m 尝试使用 df2['date'] = df1['date'].values - BENY
2
@i.n.n.m 啊,我猜到了。索引不相同。 - cs95
我有两个数据框,其中一个具有范围索引,另一个具有整数索引,并且其值在该范围内。查看数据框时,索引似乎很好,但交集为空。因此,我不得不使用to_numpy()。 - LyteFM
有没有想法如何使列名动态化,而不是硬编码的? - Manu Batham

47

试试这个?

df2['date'] = df1['date'].values
df2['hour'] = df1['hour'].values

这比被接受的解决方案更好! - Gokul nath
当数据很大(约10^5),速度非常慢,有什么办法吗? - lemmingxuan

0

我知道我来晚了,但是这种格式对我很有效。

df2.insert(1, value=df1['Name'], column='Name')

你也可以在那个值集参数中对df1执行函数。希望这有所帮助。


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