【问题标题】:python pandas data frame if else without iterating thought data framepython pandas dataframe if else 不遍历数据框
【发布时间】:2014-06-22 08:02:38
【问题描述】:

我想在 df 中添加一列。这个新 df 的值将取决于其他列的值。例如

dc = {'A':[0,9,4,5],'B':[6,0,10,12],'C':[1,3,15,18]}
df = pd.DataFrame(dc)
   A   B   C
0  0   6   1
1  9   0   3
2  4  10  15
3  5  12  18

现在我想添加另一列 D,其值将取决于 A、B、C 的值。 因此,例如,如果正在迭代 df 我会这样做:

for row in df.iterrows():
    if(row['A'] != 0 and row[B] !=0):
         row['D'] = (float(row['A'])/float(row['B']))*row['C']
    elif(row['C'] ==0 and row['A'] != 0 and row[B] ==0):
         row['D'] == 250.0
    else:
         row['D'] == 20.0 

有没有办法在没有 for 循环或使用 where () 或 apply () 函数的情况下做到这一点。

谢谢

【问题讨论】:

    标签: python numpy pandas dataframe


    【解决方案1】:

    .where 可以比.apply 快得多,所以如果你所做的只是 if/elses 那么我的目标是.where。当您在某些情况下返回标量时,np.where 将比 pandas 自己的 .where 更易于使用。

    import pandas as pd
    import numpy as np
    df['D'] = np.where((df.A!=0) & (df.B!=0), ((df.A/df.B)*df.C),
              np.where((df.C==0) & (df.A!=0) & (df.B==0), 250,
              20))
    
       A   B   C     D
    0  0   6   1  20.0
    1  9   0   3  20.0
    2  4  10  15   6.0
    3  5  12  18   7.5
    

    对于像这样的小 df,您无需担心速度。但是,在 randn 的 10000 行 df 上,这几乎比上面的 .apply 解决方案快 2000 倍:3ms 与 5850ms。也就是说,如果速度不是问题,那么 .apply 通常更易于阅读。

    【讨论】:

      【解决方案2】:

      apply 应该很适合你:

      In [20]: def func(row):
                  if (row == 0).all():
                      return 250.0
                  elif (row[['A', 'B']] != 0).all():
                      return (float(row['A']) / row['B'] ) * row['C']
                  else:
                      return 20
             ....:     
      
      
      In [21]: df['D'] = df.apply(func, axis=1)
      
      In [22]: df
      Out[22]: 
         A   B   C     D
      0  0   6   1  20.0
      1  9   0   3  20.0
      2  4  10  15   6.0
      3  5  12  18   7.5
      
      [4 rows x 4 columns]
      

      【讨论】:

      • 非常感谢!也可以这样工作。 code elif (row[['A', 'B']] != 0 and row['C'] != None).all(): 我也必须检查 None 条件
      • 您可能应该将那些Nones 转换为NaNs。您将获得更好的性能,因为它将是 float dtype 而不是 column,并且 pandas 操作是 NaN 感知的。
      • 哦,好的,谢谢!所以像这样? elif (row[['A', 'B']] != 0 and row['C'] != NaN).all()
      • 这仅取决于您希望如何处理 NaN。如果你在row['C']NaN 时返回NaN,那么你甚至不需要这种情况,因为x * NaNNaN。如果要返回 0,可以在 applying fund 之后执行 fillna(0)。此外,由于各种原因,np.nan == np.nan 总是 False,所以你的方法不太适用。 Pandas 提供了 pd.isnull 函数来检查 NaN。
      • 谢谢。我只是想看看语法是否正确。感谢您的帮助。
      【解决方案3】:

      这是一个开始:

      df['D'] = np.nan
      df['D'].loc[df[(df.A != 0) & (df.B != 0)].index] = df.A / df.B.astype(np.float) * df.C
      

      编辑,除非出于某种原因您真的关心整数,否则您可能应该继续将整个内容转换为浮点数:

      df = df.astype(np.float)
      

      然后您就不必不断地在通话本身中进行转换

      【讨论】:

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