在 Pandas 中按列进行累加并使用 if 条件

3

抱歉,我不太擅长言辞,所以我只会举一个例子来说明我想要找的东西。

ID    date1   date2   date3   date4   date5   date6
001   0       5       10      15      5       40
002   0       20      50      0       10      15
003   5       15      5       30      10      0


如果我有一个物品价格的数据框,有没有一种方法可以按列求和并应用 if 条件,并更新数据框中的值?例如,如果总和小于 10,则返回相同金额,如果大于等于 10,则返回 2 倍金额,如果大于等于 50,则返回 3 倍金额。
我想得到以下数据框作为结果:
ID    date1   date2   date3   date4   date5   date6
001   0       5       20      30      10      120
002   0       40      150     0       30      45
003   5       30      10      90      30      0
    

在ID为000的情况下,由于date2 < 10,因此date2保持不变,但是由于总金额为5 + 10 > 10,所以date3翻倍为10x2,在date4和date5上也是同样的情况,但是对于date6则是三倍。


你想要这是整个行的累加和,还是只是相邻单元格的累加和有点不清楚?(你使用了列这个术语,但我认为你想对每一行的单元格进行操作和求和?) - Carl F. Corneil
4个回答

7
您可以像筛选日期一样筛选列,然后沿着axis=1对这些列进行cumsum累加,最后使用指定条件和相应选择的np.select来获取最终结果:

filter

s = df.filter(like='date')
cs = s.cumsum(1) # cummulative sum along axis=1
df[s.columns] = np.select([cs.ge(50), cs.ge(10)], [s*3, s*2], s)

    ID  date1  date2  date3  date4  date5  date6
0  001      0      5     20     30     10    120
1  002      0     40    150      0     30     45
2  003      5     30     10     90     30      0

1
你可以以向量化的方式映射值,将bool转换为int
x = df.iloc[:, 1:].cumsum(axis=1)
df.iloc[:, 1:] = (x.ge(50).astype(int) + x.ge(10).astype(int) + 1).mul(df.iloc[:, 1:])

所以:

(x.ge(50).astype(int) + x.ge(10).astype(int) + 1)

当累积和大于50时,映射到3,大于10时映射到2,否则映射到1。

输出:

    ID  date1  date2  date3  date4  date5  date6
0  001      0      5     20     30     10    120
1  002      0     40    150      0     30     45
2  003      5     30     10     90     30      0

0
    def function1(ss:pd.Series):
        for i in range(1,len(ss)):
            if (ss[i]+ss[i-1]>=50):
                ss[i]*=3
            elif (ss[i]+ss[i-1]>=10):
                ss[i]*=2
        return ss
    
    df1.apply(function1,axis=1)
    
   date1  date2  date3  date4  date5  date6
0      0      5     20     30     10    120
1      0     40    150      0     20     30
2      5     30     10     60     30      0

0

使用applymap

我可能误解了问题,如果您只想对每个单元格应用计算,而不考虑每列的总和,则可以这样做。

您可以定义自己的自定义函数,然后使用pandas.DataFrame.applymap(function_name)将其应用于每个单元格。

import pandas as pd

# DataFrame creation
cols = ['date1', 'date2',  'date3',   'date4',   'date5',   'date6']
index = ['001', '002', '003']
data = [[0,       5,       10,      15,      5,       40],
        [0,       20,      50,      0,       10,      15],
        [5,       15,      5,       30,      10,      0]]
df = pd.DataFrame(data)
df.columns = cols
df.index = index
df.index.name = 'ID'

# Define custom function
def custom_multiply(x):
    if x < 10:
        return x
    elif x < 50:
        return x * 2
    elif x >= 50:
        return x * 3

# Apply function to all cells and reassign to df-object
df = df.applymap(custom_multiply)
df

你应该将函数应用于累积和,而不是直接应用于数字 - 同时我会放置明确的注释,说明你将“ID”列转换为索引,因为在OP的问题中它是一个常规列。 - Grzegorz Skibinski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接