【问题标题】:Python new column based on NaN in other columnsPython新列基于其他列中的NaN
【发布时间】:2015-03-30 09:59:48
【问题描述】:

我对 Python 很陌生,这是我的第一个问题,所以请对我温柔一点!

我已经尝试过其他类似问题的答案,但仍然很困难。

我正在使用 Pandas,我有一个数据框,它是多个不同 SQL 表的合并,看起来像这样:

Col_1   Col_2   Col_3   Col_4
1       NaN     NaN     NaN
2       Y       NaN     NaN
3       Z       C       S
4       NaN     B       W

我不关心 Col_2 Col_3 和 Col_4 中的值(请注意,这些值可以是字符串、整数或对象,具体取决于列)

我只关心这些列中至少有一个已填充,因此理想情况下希望第五列如下:

Col_1   Col_2   Col_3   Col_4   Col_5
1       NaN     NaN     NaN     0
2       Y       NaN     NaN     1
3       Z       C       S       1
4       NaN     B       W       1

然后我想删除列 Col_2 到 Col_4。

我最初的想法是类似于下面的函数,但这会将我的数据框从 50000 行减少到 50 行。我不想删除任何行。

def function(row):
   if (isnull.row['col_2'] and isnull.row['col_3'] and isnull.row['col_3'] is None):
      return '0'
   else:
      return '1'

df['col_5'] = df.apply(lambda row: function (row),axis=1)

任何帮助将不胜感激。

【问题讨论】:

  • 我猜你正在使用 pandas DataFrame。我已在您的问题中添加了 pandas 标签。一般来说,如果您使用的第三方库(如 pandas)不属于 Python 标准库,则需要说明。
  • 谢谢,我也会更新问题

标签: python pandas boolean nan nonetype


【解决方案1】:

使用any 并传递参数axis=1,它会逐行测试这将产生一个布尔数组,当转换为int 时,会将所有True 值转换为1False 值到0,这将比调用 apply 快得多,后者将逐行迭代并且会非常慢:

In [30]:

df['Col_5'] = any(df[df.columns[1:]].notnull(), axis=1).astype(int)
df
Out[30]:
   Col_1 Col_2 Col_3 Col_4  Col_5
0      1   NaN   NaN   NaN      0
1      2     Y   NaN   NaN      1
2      3     Z     C     S      1
3      4   NaN     B     W      1

In [31]:

df = df[['Col_1', 'Col_5']]
df
Out[31]:
   Col_1  Col_5
0      1      0
1      2      1
2      3      1
3      4      1

这是any的输出:

In [34]:

any(df[df.columns[1:]].notnull(), axis=1)
Out[34]:
array([False,  True,  True,  True], dtype=bool)

时间

In [35]:

%timeit df[df.columns[1:]].apply(lambda x: all(x.isnull()) , axis=1).astype(int)
%timeit any(df[df.columns[1:]].notnull(), axis=1).astype(int)
100 loops, best of 3: 2.46 ms per loop
1000 loops, best of 3: 1.4 ms per loop

所以在你的 df 这个大小的测试数据上,我的方法比其他答案快 2 倍以上

更新

当您运行 pandas 版本 0.12.0 时,您需要调用顶级 notnull 版本,因为该方法在 df 级别不可用:

any(pd.notnull(df[df.columns[1:]]), axis=1).astype(int)

我建议您升级,因为您将获得更多功能和错误修复。

【讨论】:

  • 我相信 OP 希望在行、列对上执行 OR 操作,其中您的实现是 AND 操作。如果第 2-4 列中至少存在 1 个非 NaN 值,则 OP 只想使 col5 为真。
  • @aus_lacy 实际上我只需要反转操作,而不是 OR 它
  • 我尝试将 any()~ 与您的实现一起使用,但无法正常工作,所以我很想看看您的反转。
  • @aus_lacy 我已经更新了,但我需要整理一下
  • notnull()。错过了那个。
【解决方案2】:

使用函数:

df['col_5'] =df.apply(lambda x: all(x.isnull()) , axis=1)

因为我的钱更容易阅读。不确定哪个更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-01
    • 2018-09-26
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 2022-10-15
    • 1970-01-01
    • 2021-12-30
    相关资源
    最近更新 更多