【问题标题】:How to evaluate conditions after each other in Pandas .loc?如何在 Pandas .loc 中逐个评估条件?
【发布时间】:2022-01-07 00:01:20
【问题描述】:

我有一个 Pandas DataFrame,其中 B 列包含混合类型

    A   B   C
0   1   1   False
1   2   abc False
2   3   2   False
3   4   3   False
4   5   b   False

B 列中的值是int 类型并且值也大于或等于3 时,我想将列C 修改为True。所以在这个例子中df['B'][3] 应该匹配这个条件

我尝试过这样做:

df.loc[(df['B'].astype(str).str.isdigit()) & (df['B'] >= 3)] = True

但是由于B 列内的str 值,我收到以下错误:

TypeError: '>' 在 'str' 和 'int' 的实例之间不支持

如果我只能在第一个条件之后提供的子集上测试第二个条件,我认为这将解决我的问题。我该怎么做才能做到这一点?

【问题讨论】:

    标签: python pandas dataframe conditional-statements


    【解决方案1】:

    有很多方法可以解决这个问题(例如,使用带有 df.apply 的自定义 (lambda) 函数,首先使用 df.replace()),但我认为最简单的方法可能是使用中间列。 首先,创建一个新列进行第一次检查,然后对这个新列进行第二次检查。

    【讨论】:

      【解决方案2】:

      一种解决方案可能是:

      df["B"].apply(lambda x: str(x).isdigit() and int(x) >= 3)
      

      如果 x 不是数字,则评估将停止并且不会尝试将 x 解析为 int - 如果参数不可解析为 int,则会抛出 ValueError

      【讨论】:

      • 这是一个很好的答案
      • 需要将整数转换为字符串才能使用 isdigit:df["B"].apply(lambda x: str(x).isdigit() and x >= 3)
      • @Paul 是的 - 这是正确的 - 假设所有元素都包含字符串(我加载了我在内存中的数据框)。让我修改一下!喜欢评论
      【解决方案3】:

      这行得通(尽管 nikeros 的回答更优雅)。

      def check_maybe_int(n):
          return int(n) >= 3 if n.isdigit() else False
      
      df.B.apply(check_maybe_int)
      

      但真正的答案是,不要这样做!混合列阻止了 Pandas 的许多优化。 apply 没有向量化,所以它比向量 int 比较慢很多。

      【讨论】:

      • Paul 对我的帖子发表了中肯的评论。如果使用 int 调用 check_maybe_int 也会抛出错误 - 比如 check_maybe_int(4)
      • true,解决方案将是相同的更改:if str(n).isdigit()。但我宁愿写一个更简单的答案,而不是涵盖所有边缘情况的答案,因为 OP 没有指定
      【解决方案4】:

      不使用 apply 的好方法是将pd.to_numericerrors='coerce' 一起使用,这会将str 类型更改为NaN,而不更改B 列的类型:

      df['C'] = pd.to_numeric(df.B, 'coerce') >= 3
      
      >>> print(df) 
      
         A    B      C
      0  1    1  False
      1  2  abc  False
      2  3    2  False
      3  4    3   True
      4  5    b  False
      

      【讨论】:

      • 不错!更简单的是df['C'] = pd.to_numeric(df.B, 'coerce') >= 3
      【解决方案5】:

      您可以使用apply(type) 如图所示

      d = {'col1': [1, 2,1, 2], 'col2': [3, 4,1, 2],'col3': [1, 2,1, 2],'col4': [1, 'e',True, 2.345]}
      df = pd.DataFrame(data=d)
      a = df.col4.apply(type)
      b = [ i==str for i in a  ]
      df['col5'] = b
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-15
        • 2016-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多