Pandas DataFrame在写入操作后包含NaN

Min*_*tex 7 python pandas

这是我的问题的最小工作示例:

import pandas as pd

columns = pd.MultiIndex.from_product([['a', 'b', 'c'], range(2)])
a = pd.DataFrame(0.0, index=range(3),columns=columns, dtype='float')
b = pd.Series([13.0, 15.0])

a.loc[1,'b'] = b  # this line results in NaNs
a.loc[1,'b'] = b.values  # this yields correct behavior
Run Code Online (Sandbox Code Playgroud)

为什么第一个作业不正确?两个系列似乎都有相同的索引,所以我认为它应该产生正确的结果.

我正在使用熊猫0.17.0.

unu*_*tbu 4

当你写的时候

a.loc[1,'b'] = b
Run Code Online (Sandbox Code Playgroud)

并且b是一个 Series, 的索引b必须与 生成的索引器完全匹配,a.loc[1,'b']以便b将 中的值复制到 中a。然而,事实证明,当a.columns是 a时MultiIndex的索引器a.loc[1,'b']是:

(Pdb) p new_ix
Index([(u'b', 0), (u'b', 1)], dtype='object')
Run Code Online (Sandbox Code Playgroud)

而 的索引b

(Pdb) p ser.index
Int64Index([0, 1], dtype='int64')
Run Code Online (Sandbox Code Playgroud)

它们不匹配,因此

(Pdb) p ser.index.equals(new_ix)
False
Run Code Online (Sandbox Code Playgroud)

由于值未对齐,因此您所属的代码分支会分配

(Pdb) p ser.reindex(new_ix).values
array([ nan,  nan])
Run Code Online (Sandbox Code Playgroud)

我通过添加pdb.set_trace()到您的代码中发现了这一点:

import pandas as pd

columns = pd.MultiIndex.from_product([['a', 'b', 'c'], range(2)])
a = pd.DataFrame(0.0, index=range(3),columns=columns, dtype='float')
b = pd.Series([13.0, 15.0])
import pdb
pdb.set_trace()
a.loc[1,'b'] = b  # this line results in NaNs
a.loc[1,'b'] = b.values  # this yields correct behavior
Run Code Online (Sandbox Code Playgroud)

并简单地在“高级别”单步执行它并发现问题发生在

        if isinstance(value, ABCSeries):
            value = self._align_series(indexer, value)
Run Code Online (Sandbox Code Playgroud)

然后再次单步执行(使用更细齿的梳子),并从调用 的行开始设置断点self._align_series(indexer, value)


请注意,如果将 的索引b也更改为 MultiIndex:

b = pd.Series([13.0, 15.0], index=pd.MultiIndex.from_product([['b'], [0,1]]))
Run Code Online (Sandbox Code Playgroud)

然后

import pandas as pd

columns = pd.MultiIndex.from_product([['a', 'b', 'c'], range(2)])
a = pd.DataFrame(0.0, index=range(3),columns=columns, dtype='float')
b = pd.Series([13.0, 15.0], index=pd.MultiIndex.from_product([['b'], [0,1]]))
a.loc[1,'b'] = b  
print(a)
Run Code Online (Sandbox Code Playgroud)

产量

   a      b      c   
   0  1   0   1  0  1
0  0  0   0   0  0  0
1  0  0  13  15  0  0
2  0  0   0   0  0  0
Run Code Online (Sandbox Code Playgroud)