Pandas DataFrame在写入操作后包含NaN

时间:2015-11-11 22:30:15

标签: 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

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

我正在使用pandas 0.17.0。

2 个答案:

答案 0 :(得分:4)

写作时

a.loc[1,'b'] = b

b是一个系列,b的索引必须与a.loc[1,'b']生成的索引器完全匹配才能将b中的值复制到{ {1}}。但事实证明,当aa.columns时,the indexer for a.loc[1,'b']为:

MultiIndex

(Pdb) p new_ix Index([(u'b', 0), (u'b', 1)], dtype='object') 的索引是

b

它们不匹配,因此

(Pdb) p ser.index
Int64Index([0, 1], dtype='int64')

由于值未对齐,the code branch you fall into会分配

(Pdb) p ser.index.equals(new_ix)
False

我通过在代码中添加(Pdb) p ser.reindex(new_ix).values array([ nan, nan]) 找到了这个:

pdb.set_trace()

然后在“高级别”单步执行并找到the problem occurs in

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

然后再次踩过它(用一把更细的梳子),从一个叫做 if isinstance(value, ABCSeries): value = self._align_series(indexer, value) 的线开始有一个断点。

请注意,如果您将self._align_series(indexer, value)的索引更改为MultiIndex:

b

然后

b = pd.Series([13.0, 15.0], index=pd.MultiIndex.from_product([['b'], [0,1]]))

产量

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)

答案 1 :(得分:1)

您可以直接将b分配到a中的列,因为b不是多索引系列。更改b会使其有效:

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

a.loc[1,'b'] = b
print(a)

产量

   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

使用b.values的另一种情况可能有效,因为Pandas会在b中获取面值,并尝试对提供的值进行最合理的分配。