在pandas数据框的MultiIndex中用None替换nan

3
我正在尝试在pandas dataframe MultiIndex中用None替换nan。似乎在MultiIndex中将None转换为nan(但在其他索引类型中不会)。
以下代码无效(摘自问题Replace NaN in DataFrame index):
df = pd.DataFrame([['a', True, 1], ['b', True, 2], ['c', False, 3], ['d', None, 4]], columns=['c1', 'c2', 'c3'])
df.set_index(['c1','c2'], inplace=True)
df.index = pd.MultiIndex.from_frame(df.index.to_frame().fillna(np.nan).replace([np.nan], [None]))
df
          c3
c1 c2       
a  True    1
b  True    2
c  False   3
d  NaN     4
type(df.index[3][1])
<class 'float'>


这句话的意思是“也不”。
index_tuples = [tuple(row) for row in df.index.to_frame().fillna(np.nan).replace([np.nan], [None]).values]
pd.MultiIndex.from_tuples(index_tuples)
MultiIndex([('a',  True),
            ('b',  True),
            ('c', False),
            ('d',   nan)],
           )

type(df.index[3][1])
<class 'float'>


似乎在MultiIndex中,None被转换为NaN。
注:对于其他索引类型,它是有效的。
df = pd.DataFrame([['a', True, 1], ['b', True, 2], ['c', False, 3], ['d', None, 4]], columns=['c1', 'c2', 'c3'])
df.set_index('c2', inplace=True)
>>> df
      c1  c3
c2          
True   a   1
True   b   2
False  c   3
NaN    d   4
>>> df.index = df.index.fillna(value=np.nan).to_series().replace([np.nan], [None])
>>> df
      c1  c3
c2          
True   a   1
True   b   2
False  c   3
NaN    d   4
>>> type(df.index[3])
<class 'NoneType'>
>>> 


1
它必须是None,或者"None"或其他什么也可以吗? - Marco_CH
它必须是None。这些数据框经过管道处理并转换为其他Python类型。此外,如果我用任意字符串替换值,则担心数据库中会有相同的非空字符串值(可能存在像“None”这样的字符串值)。 - Gofrette
2个回答

2
我唯一的方法是直接操作numpy数组。似乎在pandas中,通过MultiIndex分配None值会导致转换为NaN
import pandas as pd
import numpy as np
df = pd.DataFrame([['a', True, 1], ['b', True, 2], ['c', False, 3], ['d', None, 4]], columns=['c1', 'c2', 'c3'])
df.set_index(['c1','c2'], inplace=True)

def replace_nan(x):
    new_x = []
    for v in x:
      try:
        if np.isnan(v):
          new_x.append(None)
        else:
          new_x.append(v)
      except TypeError:
        new_x.append(v)
    return tuple(new_x)


print('Before:\n', df.index)
idx = df.index.values
idx[:] = np.vectorize(replace_nan, otypes=['object'])(idx) # Replace values in np.array
print('After:\n', df.index)

结果:

Before:
 MultiIndex([('a',  True),
            ('b',  True),
            ('c', False),
            ('d',   nan)],
           names=['c1', 'c2'])
After:
 MultiIndex([('a',  True),
            ('b',  True),
            ('c', False),
            ('d',  None)],
           names=['c1', 'c2'])

就我所知,如果你能使用.from_product()创建索引,那么你可以避免这个问题。 - Charlie Clark

1

我认为Pandas这里实际上可能存在一个bug。但是在类似的情况下,以下方法对我有效:

df = df.set_index(pf.MultiIndex.from_product(df.index.levels))

问题在于df.index.levels相同,无论是否扩展索引。


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