【问题标题】:Apply a function on a column of a dataframe depending on the value of another column and then groupby根据另一列的值在数据框的列上应用函数,然后按 groupby
【发布时间】:2019-08-26 11:31:51
【问题描述】:

假设数据框具有“A”列和“条件”列,如下面的代码所示。

example = pd.DataFrame({'A': range(10), 'condition': [0,1,0,1,2,0,1,2,2,1]})

如果“B”列中的值是 0 或 2,我想将“A”列中的值乘以 2。所以我尝试了这些:

example['A']=example['A'].apply(lambda x: x*2 \
             if example['condition']==0 or example['condition']==2)

example['A']=np.where(example.condition==0 or example.condition==2, \
             lambda x: x*2, example.A)

但这些都无法获得如下所需的输出:

    output:                 desired output:
    example                 example
       A  B                          A  B
    0  0  0                      0   0  0
    1  1  1                      1   1  1
    2  2  0                      2   4  0
    3  3  1                      3   3  1
    4  4  2                      4   8  2
    5  5  0                      5  10  0
    6  6  1                      6   6  1
    7  7  2                      7  14  2 
    8  8  2                      8  16  2 
    9  9  1                      9   9  1  

如果我得到所需的输出,我想对“条件”进行分组,并在“A”值大于 2.5 时计算“A”值的绝对总和。我有这个想法,但如果我没有从上面得到所需的输出,我不确定它是否有效。

group1=example.groupby([example[condition')['A'].\
       agg([ ('A sum' , lambda x : x[x>=2.5].abs(sum()) ])

有什么建议吗?

【问题讨论】:

    标签: python-3.x pandas dataframe lambda


    【解决方案1】:

    如果“B”列中的值为 0 或 2,您可以使用 np.where 将“A”列中的值乘以 2。

    example['A'] = np.where(example['condition'].isin([0,2]), example['A']*2,example['A'])
    

    如果条件列满足条件,要对 A 执行求和,您可以首先在数据框示例中包含一个新列,说明 A 是 > 还是

    example['check_A'] =np.where(example['A']>2.5,1,0)
    new = example.groupby(['condition','check_A'])['A'].apply(lambda c: c.abs().sum())
    

    【讨论】:

    • 谢谢,只是一个简单的问题:您将如何应用绝对求和?我需要求和,然后计算求和值的 abs()。
    【解决方案2】:

    首先我们得到condition is 0 or 2 所在的所有行。然后我们multiplyA 值通过其中两行并使用GroupBy.sum,同时使用query 过滤所有A >= 2.5 所在的行

    m = example['condition'].isin([0,2])
    example['A'] = np.where(m, example['A'].mul(2), example['A'])
    grpd = example.query('A.ge(2.5)').groupby('condition', as_index=False)['A'].sum()
    

    输出

       condition   A
    0          0  28
    1          1  18
    2          2  76
    

    详情GroupBy.sum:

    首先我们使用query 来获取A >= 2.5 所在的所有行:

    example.query('A.ge(2.5)')
    
        A  condition
    2   4          0
    3   3          1
    4   8          2
    5  10          0
    6   6          1
    7  14          2
    8  16          2
    9   9          1
    

    然后我们在条件上使用 groupby 来获取每组唯一值,在这种情况下,所有行都有012

    for _, d in grpd.groupby('condition', as_index=False):
        print(d, '\n')
    
        A  condition
    2   8          0
    5  20          0 
    
       A  condition
    3  3          1
    6  6          1
    9  9          1 
    
        A  condition
    4  16          2
    7  28          2
    8  32          2 
    

    因此,如果我们有单独的组,我们可以使用.sum 方法对整个A 列求和:

    for _, d in grpd.groupby('condition', as_index=False):
        print(d['A'].sum(), '\n')
    
    28 
    
    18 
    
    76 
    

    【讨论】:

    • 太好了,效果很好。只是一个问题......绝对总和在这里如何工作?还有一个小转折......在我的原始数据框中,A列中的值是时间(HH:MM:SS),我希望小时(HH)等于0或2。你建议如何写这个条件?
    • @Newbielp 我添加了更多解释和细节。见编辑。
    • 这大大改变了您的问题,我认为这个问题已得到回答。随意发布一个新问题,这次正确描述您的问题。 @Newbielp
    • 非常感谢...顺便说一句,我需要仔细研究一下这种查询方法等。有趣且需要研究的东西。我应用了这个:grpd=example.groupby(['condition'])['A'].agg([ ('A sum' , lambda x : x[x>=2.5].abs().sum()) ]) 并且也工作了。但这个查询在未来肯定会有用。
    【解决方案3】:

    您在最初的尝试中非常接近。特别是,我会将条件带入它自己的单独函数中以增强可读性,然后将该函数应用于具有axis=1 的数据框:

    def f(row):
        if row["condition"] == 0 or row["condition"] == 2:
            return(int(row["A"] * 2))
        return(row["A"])   # Base condition 
    
    example['B'] = example.apply(f, axis=1)   # Apply to rows of 'example' df
    
    example.drop("condition", axis=1, inplace=True)
    
    example
    
        A   condition   B
    0   0   0   0
    1   1   1   1
    2   2   0   4
    3   3   1   3
    4   4   2   8
    5   5   0   10
    6   6   1   6
    7   7   2   14
    8   8   2   16
    9   9   1   9
    

    然后,应用您的groupby 操作:

    example[example["A"] > 2.5].groupby("condition")["A"].apply(lambda x: np.sum(np.abs(x)))
    
    condition
    0     5
    1    18
    2    19
    Name: A, dtype: int64
    

    【讨论】:

      【解决方案4】:

      试试这个,

      df.loc[df['condition']%2==0, 'A'] = df['A']*2
      

      O/P:

          A  condition
      0   0          0
      1   1          1
      2   4          0
      3   3          1
      4   8          2
      5  10          0
      6   6          1
      7  14          2
      8  16          2
      9   9          1
      

      【讨论】:

      • 谢谢,我可以根据您的建议调整我必须做的其他计算。
      猜你喜欢
      • 2018-01-18
      • 1970-01-01
      • 2017-11-11
      • 2022-12-06
      • 2016-02-11
      • 1970-01-01
      • 2018-11-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多