Pandas - 用空的python dict对象替换DataFrame中的所有NaN值

时间:2014-09-17 19:34:03

标签: python pandas

我有一个pandas DataFrame,其中每个单元格都包含一个python dict。

>>> data = {'Q':{'X':{2:2010}, 'Y':{2:2011, 3:2009}},'R':{'X':{1:2013}}}
>>> frame = DataFrame(data)
>>> frame
                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}        NaN

我想用空的dict替换NaN,以获得这个结果:

                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}        {}

但是,因为fillna函数将空字典解释为标量值而不是列的映射 - >价值,如果我只是这样做就没有了(即它不起作用):

>>> frame.fillna(inplace=True, value={})
                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}        NaN

有没有办法使用fillna来实现我的目标? 我是否必须遍历整个DataFrame或构建一个愚蠢的字典,并将所有列映射到空字典?

6 个答案:

答案 0 :(得分:10)

我能够以这种方式使用DataFrame.applymap

>>> from pandas import isnull
>>> frame=frame.applymap(lambda x: {} if isnull(x) else x)
>>> frame
                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}         {}

这个解决方案避免了EdChum解决方案中的陷阱(所有NaN单元都指向内存中相同的底层dict对象,阻止它们彼此独立更新)和Shashank(需要潜在的大型数据结构)用嵌套的dicts构造,只是为了指定一个空的dict值。)

答案 1 :(得分:2)

这可以使用loc

In [6]:

frame.loc[frame['R'].isnull(), 'R'] = {}
frame
Out[6]:
                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}         {}

答案 2 :(得分:2)

问题是当dict传递给fillna时,它会尝试根据框架中的列填充值。所以我尝试的第一个解决方案是 -

frame.fillna({column: {} for column in frame.columns})

但是如果在这样的第二级提供字典,它会尝试将键与索引匹配,因此有效的解决方案是 -

frame.fillna({column: {ind: {} for ind in frame.index} for column in frame.columns})

哪个给出 -

                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}         {}

EdChum的答案可能更适合您的需求,但是当您不想进行更改时,可以使用此答案。

编辑:上面的解决方案适用于较小的帧,但对于较大的帧可能是一个问题。使用replace可以解决这个问题。

frame.replace(np.nan, {column: {} for column in frame.columns})

答案 3 :(得分:0)

使用#include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { unsigned int code = 0; FILE *fp; fp = fopen(argv[1], "r+"); int result = fscanf(fp, "%x", &code); printf("\n hex-1: %08X, decimal-1: %d \n", code, code); printf("\n%x\n", code >>26); printf("\n%x\n", code >>21 & 0x0b00000011111); //what can i do to change this while (result != EOF) { result = fscanf(fp, "%x", &code); printf("\n read hex: %08X, decimal: %d \n", code, code); if(feof(fp)) { puts("EOF"); break; }//if }//while } 访问器直接分配到numpy数组:

.values

答案 4 :(得分:0)

DataFrame.where是一种非常直接的实现此目的的方法:

>>> data = {'Q': {'X': {2: 2010}, 'Y': {2: 2011, 3: 2009}}, 'R': {'X': {1: 2013}}}
>>> frame = DataFrame(data)
>>> frame
                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}        NaN

>>> frame.where(frame.notna(), lambda x: [{}])
                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}         {}

而且,它似乎更快一些:

>>> %timeit frame.where(frame.notna(), lambda x: [{}])
791 µs ± 16.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit frame.applymap(lambda x: {} if isnull(x) else x)
1.07 ms ± 7.15 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

(在较大的数据集上,我观察到速度提高了约10倍)

答案 5 :(得分:0)

@Josh_Bode 的回答对我帮助很大。这是一个略有不同的版本。我使用了 mask() 而不是 where() (非常微不足道的变化)。我还更新了分配空字典的方式。通过创建一个与框架一样长的 dict 实例列表,然后分配它,我避免了同一 dict 的多个副本的陷阱。

>>> data = {'Q': {'X': {2: 2010}, 'Y': {2: 2011, 3: 2009}}, 'R': {'X': {1: 2013}}}
>>> frame = DataFrame(data)
>>> frame
                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}        NaN

>>> frame.mask(frame.isna(), lambda x: [{} for _ in range(len(frame)])
                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}         {}