Pandas Dataframe:用行平均值替换NaN

Aen*_*aon 14 python missing-data dataframe pandas

我正在努力学习大熊猫,但我对以下内容感到困惑.我想替换NaNs是一个具有行平均值的数据帧.因此,类似的东西df.fillna(df.mean(axis=1))应该工作,但由于某种原因,它失败了.我错过了什么,我做错了什么?是因为它没有实施; 看到这里的链接

import pandas as pd
import numpy as np
?
pd.__version__
Out[44]:
'0.15.2'

In [45]:
df = pd.DataFrame()
df['c1'] = [1, 2, 3]
df['c2'] = [4, 5, 6]
df['c3'] = [7, np.nan, 9]
df

Out[45]:
    c1  c2  c3
0   1   4   7
1   2   5   NaN
2   3   6   9

In [46]:  
df.fillna(df.mean(axis=1)) 

Out[46]:
    c1  c2  c3
0   1   4   7
1   2   5   NaN
2   3   6   9
Run Code Online (Sandbox Code Playgroud)

但是这样的事情看起来很好

df.fillna(df.mean(axis=0)) 

Out[47]:
    c1  c2  c3
0   1   4   7
1   2   5   8
2   3   6   9
Run Code Online (Sandbox Code Playgroud)

And*_*den 25

如注释,fillna的axis参数是NotImplemented.

df.fillna(df.mean(axis=1), axis=1)
Run Code Online (Sandbox Code Playgroud)

注意:这在此非常关键,因为您不希望用第n行平均值填充第n列.

现在你需要迭代:

In [11]: m = df.mean(axis=1)
         for i, col in enumerate(df):
             # using i allows for duplicate columns
             # inplace *may* not always work here, so IMO the next line is preferred
             # df.iloc[:, i].fillna(m, inplace=True)
             df.iloc[:, i] = df.iloc[:, i].fillna(m)

In [12]: df
Out[12]:
   c1  c2   c3
0   1   4  7.0
1   2   5  3.5
2   3   6  9.0
Run Code Online (Sandbox Code Playgroud)

另一种方法是填充转置然后转置,这可能更有效...

df.T.fillna(df.mean(axis=1)).T
Run Code Online (Sandbox Code Playgroud)


Cle*_*leb 12

作为替代方案,您还可以使用apply带有这样的lambda表达式:

df.apply(lambda row: row.fillna(row.mean()), axis=1)
Run Code Online (Sandbox Code Playgroud)

屈服也

    c1   c2   c3
0  1.0  4.0  7.0
1  2.0  5.0  3.5
2  3.0  6.0  9.0
Run Code Online (Sandbox Code Playgroud)


小智 6

要获得有效的解决方案,请使用DataFrame.where

\n

我们可以where使用axis=0

\n
df.where(df.notna(), df.mean(axis=1), axis=0)\n
Run Code Online (Sandbox Code Playgroud)\n

maskaxis=0

\n
df.mask(df.isna(), df.mean(axis=1), axis=0)\n
Run Code Online (Sandbox Code Playgroud)\n

通过使用axis=0,我们可以用行平均值填充每列中的缺失值。

\n

这些方法的执行非常相似(where在大型 DataFrame (300_000, 20) 上表现稍好),并且比此处发布的 numpy 方法快约 35-50%,并且比双转置方法快 110 倍。

\n

一些基准:

\n
df = creator()\n\n>>> %timeit df.where(df.notna(), df.mean(axis=1), axis=0)\n542 ms \xc2\xb1 3.36 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n\n>>> %timeit df.mask(df.isna(), df.mean(axis=1), axis=0)\n555 ms \xc2\xb1 21.4 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n\n>>> %timeit df.fillna(0) + df.isna().values * df.mean(axis=1).values.reshape(-1,1)\n751 ms \xc2\xb1 22 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n\n>>> %timeit fill = pd.DataFrame(np.broadcast_to(df.mean(1).to_numpy()[:, None], df.shape), columns=df.columns, index=df.index); df.update(fill, overwrite=False)\n848 ms \xc2\xb1 22.8 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n\n>>> %timeit df.apply(lambda row: row.fillna(row.mean()), axis=1)\n1min 4s \xc2\xb1 5.32 s per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n\n>>> %timeit df.T.fillna(df.mean(axis=1)).T\n1min 5s \xc2\xb1 2.4 s per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n\ndef creator():\n    A = np.random.rand(300_000, 20)\n    A.ravel()[np.random.choice(A.size, 300_000, replace=False)] = np.nan\n    return pd.DataFrame(A)\n
Run Code Online (Sandbox Code Playgroud)\n