【问题标题】:How to put NaN in Pandas Dataframe efficiently?如何有效地将 NaN 放入 Pandas Dataframe 中?
【发布时间】:2020-05-14 18:04:16
【问题描述】:

我有一个df,其中包含分类和数字数据

df = {'Name':['Tom', 'nick', 'krish', 'jack'], 
       'Address':['Oxford', 'Cambridge', 'Xianjiang', 'Wuhan'], 
       'Age':[20, 21, 19, 18], 
       'Weight':[50, 61, 69, 78]} 
df = pd.DataFrame(df) 

我需要将每列中的 50 % 随机替换为 NaN,所以结果可能如下图所示

如何用最有效的技术做到这一点,因为我有大量的行和列,我会做很多重复。

【问题讨论】:

标签: python pandas numpy dataframe nan


【解决方案1】:

将以前答案的性能提高三倍,主要受@jezrael 启发,我建议使用argpartition 而不是argsort,因为执行的排序相当无用:

df1 = df.mask(np.random.rand(*df.shape).argpartition(0, axis=0) >= df.shape[0] // 2)
print(df1)
   Name    Address   Age  Weight
0   NaN     Oxford   NaN    50.0
1  nick  Cambridge  21.0    61.0
2   NaN        NaN   NaN     NaN
3  jack        NaN  18.0     NaN

性能对比

# Reusing the same comparison dataset
df = pd.concat([df] * 50000, ignore_index=True)
df = pd.concat([df] * 50, ignore_index=True, axis=1)


# @Andy's answer, using apply and sample
%timeit df.apply(lambda x: x.sample(frac=0.5)).reindex(df.index)
9.72 s ± 532 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# @jezrael's answer, based on mask, np random and argsort
%timeit df.mask(np.random.rand(*df.shape).argsort(axis=0) >= df.shape[0] // 2)
8.23 s ± 732 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# This answer, based on mask, np random and argpartition
%timeit df.mask(np.random.rand(*df.shape).argpartition(0, axis=0) >= df.shape[0] // 2)
2.54 s ± 98.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

  • 造成这种差异的原因是什么?
  • argsort 正在获取使用np.random.rand 生成的所有随机值,对它们进行排序并为每个值设置一个索引。相反,argpartition 只是根据提供的分区信息分配索引,从而避免对整个数组进行排序。您显然不需要对所有随机值进行排序即可获得前半部分,只需获取中值并根据该中值生成分区即可。这就是 argpartition 在幕后所做的事情。
【解决方案2】:

将apply 与sample 一起使用

df_final =  df.apply(lambda x: x.sample(frac=0.5)).reindex(df.index)

Out[175]:
    Name    Address   Age  Weight
0    Tom        NaN   NaN    50.0
1    NaN        NaN   NaN    61.0
2  krish  Xianjiang  19.0     NaN
3    NaN      Wuhan  18.0     NaN

【讨论】:

  • 它的写法是每行占50%,而不是每列占50%
  • @ibarrond:如果是每行的 50%,则第 0 行的预期输出必须有 2 个NaN。 OP 预期输出或第 0 行只有 1 个 NaN
  • @ibarrond:OP 明确表示replace 50 % in each column to NaN。我是否误读了问题中的某些内容?
  • 你是对的!但是,当所有 4 个值都设置为 NaN 时,该行将被过滤掉(尝试使用更大的 df 以查看效果或多次运行您的示例)。
  • @ibarrond:啊,你是对的!它需要reindex 来处理,以防每列的随机发生在同一行。我编辑了答案
【解决方案3】:

这可以通过在元组范围内获取随机数并在它们上运行一个循环并将其视为用 NaaN 替换的索引来完成

示例: 如果你有 10 个元组 从随机数生成器集范围到 0 到 9 和 并将上述操作的结果作为索引替换为 NaN

【讨论】:

    猜你喜欢
    • 2018-07-27
    • 2018-11-30
    • 2019-08-17
    • 2021-03-31
    • 2018-05-29
    • 1970-01-01
    • 2022-01-04
    • 2018-11-30
    • 2016-04-04
    相关资源
    最近更新 更多