对pandas数据帧中单个列中的一系列单元格求和

时间:2018-01-07 03:05:38

标签: python pandas sum

我在DataFrame中有三列。我想取Streak_Count列中的数字,并总结MON TOTAL中返回的单元格数。结果显示在WANTED RESULT中,如下所示。我无法弄清楚的问题是将单元格的数量相加,可以是任何数字>>在这个例子中介于1和4之间。

scss
@import '~bootstrap/scss/bootstrap.scss';

2 个答案:

答案 0 :(得分:1)

这一切都是为了找到合适的东西来分组。在这种情况下,STREAK_COUNT的反向累积和将为您提供所需的内容。

首先我们创建数据框:

import pandas as pd

>>> df = pd.DataFrame({'MON TOTAL':[1.123077, -1.296178, -6.355612, 5.634692, 4.180605, -0.101016, -0.706125,
                                    0.368579, 3.822277, 2.233359, 15.219644, -2.647693, 1.599094],
                       'STREAK_COUNT':[1, 0, 2, 0, 2, 0, 2, 0, 0, 0, 4, 1, 1]},
                      index=['1/2/1992', '2/3/1992', '3/2/1992', '4/1/1992', '5/1/1992', '7/1/1992', '8/3/1992',
                             '10/1/1992', '11/2/1992', '1/4/1993', '2/1/1993', '3/1/1993', '4/1/1993'])
>>> df
           MON TOTAL  STREAK_COUNT
1/2/1992    1.123077             1
2/3/1992   -1.296178             0
3/2/1992   -6.355612             2
4/1/1992    5.634692             0
5/1/1992    4.180605             2
7/1/1992   -0.101016             0
8/3/1992   -0.706125             2
10/1/1992   0.368579             0
11/2/1992   3.822277             0
1/4/1993    2.233359             0
2/1/1993   15.219644             4
3/1/1993   -2.647693             1
4/1/1993    1.599094             1

接下来找到组,计算每个组的总和,并将结果连接到原始数据帧:

>>> groups = df['STREAK_COUNT'][::-1].cumsum()[::-1]
>>> df['RESULT'] = df.groupby(groups)['MON TOTAL'].transform('sum')
>>> df
           MON TOTAL  STREAK_COUNT     RESULT
1/2/1992    1.123077             1   1.123077
2/3/1992   -1.296178             0  -7.651790
3/2/1992   -6.355612             2  -7.651790
4/1/1992    5.634692             0   9.815297
5/1/1992    4.180605             2   9.815297
7/1/1992   -0.101016             0  -0.807141
8/3/1992   -0.706125             2  -0.807141
10/1/1992   0.368579             0  21.643859
11/2/1992   3.822277             0  21.643859
1/4/1993    2.233359             0  21.643859
2/1/1993   15.219644             4  21.643859
3/1/1993   -2.647693             1  -2.647693
4/1/1993    1.599094             1   1.599094

如果您只想在每条条纹结束时得到结果,请使用遮罩过滤它:

>>> df[df['STREAK_COUNT'] > 0]
          MON TOTAL  STREAK_COUNT     RESULT
1/2/1992   1.123077             1   1.123077
3/2/1992  -6.355612             2  -7.651790
5/1/1992   4.180605             2   9.815297
8/3/1992  -0.706125             2  -0.807141
2/1/1993  15.219644             4  21.643859
3/1/1993  -2.647693             1  -2.647693
4/1/1993   1.599094             1   1.599094

答案 1 :(得分:0)

编辑1:

对整个列执行操作而不是迭代并使用对象/迭代器从而避免列表的高效版本。

这里的变化是,

1)我们首先获得" STREAK_COUNT"转换为tuple,索引为第一个值," STREAK_COUNT"作为第二个使用enumerate。由于enumerate是可迭代的,我们可以在步骤(3)中直接使用它而不是转换为列表。

2)定义getTotal()函数并独立处理(1)中的每个值以生成相应的"结果"值。

3)将getTotal()映射到整个" STREAK_COUNT"枚举在步骤(1)中生成的对象以获得所需的"结果"列。

工作代码

def getTotal(x):        
        pos = [i for i in range(x[0],x[0]-x[1],-1)]
        total = sum(df.iloc[pos, 0])
        func = lambda x : x if x !=0 else ''
        return func(total)


df[ "RESULT" ] = map(lambda x: getTotal(x), enumerate(df["STREAK_COUNT"]))
print df

较早版本

效率不高,因为我们需要遍历行和列,但适用于STREAK_COUNT内的任何值,并且更清晰易懂。

示例代码

import pandas as pd

df = pd.read_csv("sample.csv", index_col = 0)

#iterate over rows with index
for idx, (lab, row) in  enumerate(df.iterrows()):
        #get current STREAK_COUNT value
    count = int(df.iloc[idx, 1])

    #get previous positions based on count
    pos = [i for i in range(idx,idx-count,-1)]

    #count total
    total = sum(df.iloc[pos, 0])

    #create new column value based on total
    func = lambda x : x if x !=0 else ''
    df.loc[lab, "RESULT"] = func(total)

print df

结果

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>> 
           MON TOTAL  STREAK_COUNT    RESULT
1/2/1992    1.123077             1   1.12308
2/3/1992   -1.296718             0          
3/2/1992   -6.355612             2  -7.65233
4/1/1992    5.634692             0          
5/1/1992    4.180605             2    9.8153
7/1/1992   -0.101016             0          
8/3/1992   -0.706125             2 -0.807141
10/1/1992   0.368579             0          
11/2/1992   3.822277             0          
1/4/1993    2.233359             0          
2/1/1993   15.219644             4   21.6439
3/1/1993   -2.647693             1  -2.64769
4/1/1993    1.599094             1   1.59909
>>>