【问题标题】:iterate over pandas columns based on conditions根据条件迭代熊猫列
【发布时间】:2021-03-06 04:32:07
【问题描述】:

想根据 count、A 和 B 的值计算 C

样本df:

count A B C
yes 23 2 nan
nan 23 1 nan
yes 41 6 nan

我想要的结果

count A B C
yes 23 2 46
nan 23 1 0
yes 41 6 246

仅当计数值 = 是时计算 C = A*B,否则 C 值 =0 也就是说,它应该跳过 count 的 nan 值

任何帮助都是可观的

我正在尝试这个

for ind, row in df.iterrows():
    if df['count'] == 'yes':
        df.loc[ ind, 'C'] =row['A'] *row['B']
    else:
        df.loc[ ind, 'C'] =0

但它给出了错误:ValueError:一个系列的真值是模棱两可的。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。

【问题讨论】:

    标签: python pandas dataframe numpy


    【解决方案1】:

    另一种选择:

    df.C = df.A.mul(df.B).where(df['count'].eq('yes')).fillna(0)
    
    df
    #  count   A  B      C
    #0   yes  23  2   46.0
    #1   NaN  23  1    0.0
    #2   yes  41  6  246.0
    

    或者如果您更喜欢运算符:df.C = (df.A * df.B).where(df['count'] == 'yes').fillna(0)

    【讨论】:

      【解决方案2】:

      pandas 重载 * 进行此操作,前提是您正确指定要设置的索引:

      mask = df["count"].notna()
      df.loc[mask, "C"] = df["A"]*df["B"]
      df.C.fillna(0, inplace=True)
      

      或更简洁的版本会惹恼您的同事:

      df["C"] = df["A"]*df["B"]*(df["count"].notna())
      

      最后,df["count"].notna() 返回一个布尔列,当与数字列相乘时转换为数字类型。简洁但清晰。

      任一输出:

        count   A  B      C
      0   yes  23  2   46.0
      1   NaN  23  1      0
      2   yes  41  6  246.0
      

      这将比.apply 性能更高,并且比 iterrows 性能更高。

      【讨论】:

      • 条件未应用
      【解决方案3】:

      就用这个吧:-

      df['C']=df[df['count']=='yes']['C'].fillna(value=df['A']*df['B'])
      df['C']=df['C'].fillna(0)
      

      试试这个:-

      for ind, row in df.iterrows():
          if row['count'] == 'yes':
              df.loc[ ind, 'C'] =row['A'] *row['B']
          else:
              df.loc[ ind, 'C'] =0
      

      你收到错误是因为你写的是df['count']=='yes'而不是row['count'] == 'yes'

      【讨论】:

        【解决方案4】:

        您可以尝试使用df.prod 将A 与B 相乘,并使用df.mask 屏蔽NaN 值。

        df['C'] = df[['A', 'B']].prod(axis=1).mask(df['count'].isna(), 0)
        
          count   A  B    C
        0   yes  23  2   46
        1   NaN  23  1    0
        2   yes  41  6  246
        

        【讨论】:

          【解决方案5】:

          最快的方法是np.where():

          df['C'] = np.where(
             df['count'] == 'yes', # condition
             df['A'] * df['B'],    # result if true
             0,                    # result if false
          )
          
              count    A    B    C
          0     yes   23    2   46
          1     NaN   23    1    0
          2     yes   41    6  246
          

          针对df = pd.concat([df] * 1000)的所有当前答案的时间安排:

          method (hyperlinked to SO answer) %timeit (mean ± SD; 7 runs, 1K loops each)
          1. np.where() 561 µs ± 23.9 µs per loop
          2. * df['count'].notna() 642 µs ± 15.4 µs per loop
          3. Series.where() with fillna() 844 µs ± 7.89 µs per loop
          4. loc[] with fillna() 1.31 ms ± 237 µs per loop
          5. Series.mask() with isna() 1.49 ms ± 280 µs per loop
          6. fillna() x2 1.63 ms ± 103 µs per loop

          【讨论】:

            猜你喜欢
            • 2022-01-01
            • 2020-09-30
            • 2019-05-04
            • 1970-01-01
            • 1970-01-01
            • 2018-12-13
            • 2021-07-26
            • 2019-04-28
            • 1970-01-01
            相关资源
            最近更新 更多