【问题标题】:Add columns to pandas Dataframe on different conditions在不同条件下将列添加到 pandas Dataframe
【发布时间】:2018-02-16 17:09:52
【问题描述】:

我有一个熊猫数据框。

import pandas as pd
data = pd.DataFrame({
'a': [0,1,0,0,1,1,0,1], 
'b': [0,0,1,0,1,0,1,1], 
'c': [0,0,0,1,0,1,1,1],
'rate': [0,0.1,0.11,0.12,0.24,0.27,0.3,0.4]})

a,b,c 是我的频道,我正在添加另一列,显示这些频道的按行总计的总和:

data['total'] = data.a + data.b + data.c

data

    a   b   c   rate    total
1   1   0   0   0.10    1
2   0   1   0   0.11    1 
3   0   0   1   0.12    1
4   1   1   0   0.24    2
5   1   0   1   0.27    2
6   0   1   1   0.30    2
7   1   1   1   0.40    3

我想处理总计 = 1 和总计 = 2 的数据

reduced = data[(data.a == 1) & (data.total == 2)]
print(reduced)

     a  b  c  rate  total
  4  1  1  0  0.24      2
  5  1  0  1  0.27      2

我想向这个简化的数据框添加列,如下所示:

      a  b  c  rate  total  prob_a  prob_b  prob_c
   4  1  1  0  0.24      2     0.1    0.11    0
   5  1  0  1  0.27      2     0.1     0      0.12

在缩减数据帧的第一行中,prob_c 为 0,因为 C 不存在(ABC => 110)。在缩减数据帧的第二行中,prob_b 为 0,因为 B 不存在(ABC => 101)

在哪里,

# Channel a alone occurs (ABC => 100)
prob_a = data['rate'][(data.a == 1) & (data.total == 1)]

# Channel b alone occurs (ABC => 010)
prob_b = data['rate'][(data.b == 1) & (data.total == 1)]

# Channel c alone occurs (ABC => 001)
prob_c = data['rate'][(data.c == 1) & (data.total == 1)]

我试过了:

reduced['prob_a'] = data['rate'][(data.a == 1) & (data.total == 1)]
reduced['prob_b'] = data['rate'][(data.b == 1) & (data.total == 1)]
reduced['prob_c'] = data['rate'][(data.c == 1) & (data.total == 1)]
print(reduced)

导致此输出:

   a  b  c  rate  total  prob_a  prob_b  prob_c
4  1  1  0  0.24      2     NaN     NaN     NaN
5  1  0  1  0.27      2     NaN     NaN     NaN

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    IIUC

    reduced['prob_a'] = data.loc[(data.a == 1) & (data.total == 1),'rate'].values[0]
    reduced['prob_b'] = data.loc[(data.b == 1) & (data.total == 1),'rate'].values[0]
    reduced['prob_c'] = data.loc[(data.c == 1) & (data.total == 1),'rate'].values[0]
    
    reduced[['prob_a','prob_b','prob_c']]=reduced[['prob_a','prob_b','prob_c']].mul(reduced[['a','b','c']].eq(1).values)
    reduced
    Out[698]: 
       a  b  c  rate  total  prob_a  prob_b  prob_c
    4  1  1  0  0.24      2     0.1    0.11    0.00
    5  1  0  1  0.27      2     0.1    0.00    0.12
    

    【讨论】:

      【解决方案2】:

      分为两步

      一个
      计算概率

      probs = data.query('a + b + c == 1').pipe(
          lambda d: d.drop('rate', 1).T.dot(d.rate)
      )
      
      probs
      
      a    0.10
      b    0.11
      c    0.12
      dtype: float64
      

      工作原理
      只获取总和等于一排:

      data.query('a + b + c == 1')
      
         a  b  c  rate
      1  1  0  0  0.10
      2  0  1  0  0.11
      3  0  0  1  0.12
      

      pipe 允许我们将结果流水线化到函数中。根据上面的结果,我想将列abc 与列rate 进行点积。通过pipelambda 允许我这样做。

      更通用的方法

      df = data.copy()
      rate = df.pop('rate')
      mask = df.sum(1) == 1
      probs = df[mask].T.dot(rate[mask])
      
      probs
      

      两个
      其余的

      data.join(
          data.drop('rate', 1).mul(probs).add_prefix('prob_')
      ).query('a + b + c == 2 and a == 1')
      
         a  b  c  rate  prob_a  prob_b  prob_c
      4  1  1  0  0.24     0.1    0.11    0.00
      5  1  0  1  0.27     0.1    0.00    0.12
      

      【讨论】:

      • 嘿,你能解释一下第一步吗 - 特别是 lambda 表达式。
      • 问题中的示例一次谈论 3 个频道。但总的来说,如果我有“N”个通道 (a,b,c,d, ... z) ,我如何编写一个函数来为我提供所有可能的配对组合的概率。例如,如果我有 5 个通道 - A、B、C、D、E。我的输出需要 5c2 = 10 行,其中每行一次只显示 2 个通道。
      • 我为你添加了一个更通用的方法
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-04
      • 1970-01-01
      • 2018-09-10
      • 2020-10-26
      • 2014-05-19
      相关资源
      最近更新 更多