哪一个更可取?np.where 还是 .loc?

Har*_*boa 8 python numpy pandas

我发现了两种根据条件替换数据框某些值的形式:

  1. .loc
mask = df['param'].isnull()
df.loc[mask, 'param'] = 'new_value'
Run Code Online (Sandbox Code Playgroud)
  1. np.where()
mask = df['param'].isnull()
df['param'] = np.where(mask, 'new_value', df['param'])
Run Code Online (Sandbox Code Playgroud)


两种形式都很好用,但哪一种是首选呢?关于这个问题,我什么时候应该使用.loc,什么时候应该使用np.where

Qua*_*ang 7

好吧,这不是一个完整的测试,但这是一个示例。在每次运行 ( loc, np.where) 中,数据都会通过种子重置为原始随机数。

\n\n

玩具数据1

\n\n

在这里,不仅仅是np.nan有效值。此外,该列是浮动类型的。

\n\n
np.random.seed(1)\ndf = pd.DataFrame({\'param\': np.random.choice((1, np.nan), 1000000, p=(0.3,0.7))})\n\n# loc\n%%timeit\nmask = df[\'param\'].isnull()\ndf.loc[mask, \'param\'] = \'new_value\'\n# 46.7 ms \xc2\xb1 177 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n\n# np.where\n%%timeit\nmask = df[\'param\'].isnull()\ndf[\'param\'] = np.where(mask, \'new_value\', df[\'param\'])\n# 86.8 ms \xc2\xb1 2.4 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

玩具数据2:

\n\n

这里的np.nan值少于有效值,并且该列是对象类型:

\n\n
np.random.seed(1)\ndf = pd.DataFrame({\'param\': np.random.choice(("1", np.nan), 1000000, p=(0.7,0.3))})\n
Run Code Online (Sandbox Code Playgroud)\n\n

相同的故事:

\n\n
df.loc[mask, \'param\'] = \'new_value\'\n# 47.8 ms \xc2\xb1 350 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n\ndf[\'param\'] = np.where(mask, \'new_value\', df[\'param\'])\n# 58.9 ms \xc2\xb1 1.72 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,与 @cs95\ 的评论相反,loc似乎表现优于np.where.

\n

  • 这应该使用玩具数据进行更新,其中“param”是数字,因为“np.where”并不真正擅长处理字符串数据。 (2认同)