用列相关的平均值替换数据框中NaN值的函数

3

编辑: 这个问题不是pandas dataframe replace nan values with average of columns的克隆,因为我想用列的平均值替换每一列的值,而不是用数据框中所有值的平均值。

问题

我有一个带有一百列的pandas数据框(train),需要应用机器学习技术。

通常情况下,我手工进行特征工程,但在这种情况下,我有很多列要处理。

我想构建一个Python函数:

1) 找到每一列中的NaN值(我考虑使用df.isnull().any()

2) 对于每个NaN值,将其替换为找到NaN值的列的平均值。

我的想法是这样的:

def replace(value):
    for value in train:
        if train['value'].isnull():
           train['value'] = train['value'].fillna(train['value'].mean())

train = train.apply(replace,axis=1)

但是我收到了以下错误信息

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/opt/conda/lib/python3.6/site-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
   3063             try:
-> 3064                 return self._engine.get_loc(key)
   3065             except KeyError:

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: 'value'

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
<ipython-input-25-003b3eb2463c> in <module>()
----> 1 train = train.apply(replace,axis=1)

/opt/conda/lib/python3.6/site-packages/pandas/core/frame.py in apply(self, func, axis, broadcast, raw, reduce, result_type, args, **kwds)
   6012                          args=args,
   6013                          kwds=kwds)
-> 6014         return op.get_result()
   6015 
   6016     def applymap(self, func):

/opt/conda/lib/python3.6/site-packages/pandas/core/apply.py in get_result(self)
    140             return self.apply_raw()
    141 
--> 142         return self.apply_standard()
    143 
    144     def apply_empty_result(self):

/opt/conda/lib/python3.6/site-packages/pandas/core/apply.py in apply_standard(self)
    246 
    247         # compute the result using the series generator
--> 248         self.apply_series_generator()
    249 
    250         # wrap results

/opt/conda/lib/python3.6/site-packages/pandas/core/apply.py in apply_series_generator(self)
    275             try:
    276                 for i, v in enumerate(series_gen):
--> 277                     results[i] = self.f(v)
    278                     keys.append(v.name)
    279             except Exception as e:

<ipython-input-22-2e7fa654e765> in replace(value)
      1 def replace(value):
      2     for value in train:
----> 3         if train['value'].isnull():
      4            train['value'] = train['value'].fillna(df['value'].mean())

/opt/conda/lib/python3.6/site-packages/pandas/core/frame.py in __getitem__(self, key)
   2686             return self._getitem_multilevel(key)
   2687         else:
-> 2688             return self._getitem_column(key)
   2689 
   2690     def _getitem_column(self, key):

/opt/conda/lib/python3.6/site-packages/pandas/core/frame.py in _getitem_column(self, key)
   2693         # get column
   2694         if self.columns.is_unique:
-> 2695             return self._get_item_cache(key)
   2696 
   2697         # duplicate columns & possible reduce dimensionality

/opt/conda/lib/python3.6/site-packages/pandas/core/generic.py in _get_item_cache(self, item)
   2484         res = cache.get(item)
   2485         if res is None:
-> 2486             values = self._data.get(item)
   2487             res = self._box_item_values(item, values)
   2488             cache[item] = res

/opt/conda/lib/python3.6/site-packages/pandas/core/internals.py in get(self, item, fastpath)
   4113 
   4114             if not isna(item):
-> 4115                 loc = self.items.get_loc(item)
   4116             else:
   4117                 indexer = np.arange(len(self.items))[isna(self.items)]

/opt/conda/lib/python3.6/site-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
   3064                 return self._engine.get_loc(key)
   3065             except KeyError:
-> 3066                 return self._engine.get_loc(self._maybe_cast_indexer(key))
   3067 
   3068         indexer = self.get_indexer([key], method=method, tolerance=tolerance)

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: ('value', 'occurred at index 0')

在寻找解决方案时,我发现:

  • 这个 解决方法可以用于txt文件,但不适用于pandas dataframe。

  • 这个 关于 df.isnull().any() 方法的问题。


感谢您发布反馈。在我看来,这不是重复问题:那个问题是用数据框的平均值替换值。我想要用每列的平均值替换每个列的值。 - Marco Giuseppe de Pinto
我认为您可以使用fillna()方法:https://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.DataFrame.fillna.html目前我正在编写示例代码。 - Pitto
哇喔,@zipa更快 :) - Pitto
它运行正常!非常完美,谢谢你们两个! - Marco Giuseppe de Pinto
这绝对是 https://dev59.com/HmMl5IYBdhLWcg3wHTug 的重复。 - AMC
3个回答

7

你也可以使用 fillna

df = pd.DataFrame({'A': [1, 2, np.nan], 'B': [2, np.nan, np.nan]})
df.fillna(df.mean(axis=0))
    A   B
0   1.0 2.0
1   2.0 2.0
2   1.5 2.0

df.mean(axis=0) 计算每列的平均值,并将其传递给 fillna 方法。

对于上述数据集,这种方法比使用 apply 方法快两倍。


6

要将每一列的 NaN 填充为其相应的均值,请使用以下方法:

df.apply(lambda x: x.fillna(x.mean())) 

4
你可以尝试以下方法:
[df[col].fillna(df[col].mean(), inplace=True) for col in df.columns]

但这只是一种实现方式。 您的代码基本正确。您的错误在于应该调用


train[value]

改为:

train['value']

在你的代码中随处可见。因为后者将尝试查找一个名为“value”的列,而这实际上是你正在迭代的列表中的变量。


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