繁体   English   中英

熊猫条件累积总和

[英]Pandas conditional cumulative sum

我正在使用介于两者之间为空值的数据。 我打算从特定列sales的累积总和中构建时间序列图。 sales累计金额的条件:(1.)如果第一行为null,则fillna(0) ,然后为cumsum()因此绘图始终可以从原点开始。 (2.)如果空行紧随fillna(0) ,请保留为空,否则fillna(0)

data = {'year': [2010, 2011, 2012, 2013, 2014, 2015, 2016,2017, 2018, 2019],
        'quantity': [10, 21, 20, 10, 39, 30, 31,45, 23, 56],
        'sales': [None, 41, None, None, 32, 0, 31,None, None, None]}

df = pd.DataFrame(data)
df = df.set_index('year')

df['cum_sales'] = df[['sales']].cumsum()

print df
df.plot()

在此处输入图片说明

如何应用条件以使结果变为:

在此处输入图片说明

我们将结合使用bfillcombine_first 当我们回填销售列时,我们会填写所有缺失值,后跟非缺失数据,从而满足条件(2)。 但是,我只用它来标识确实满足条件(2)的那些位置,因为我将把它们乘以零,然后用它来填充缺失的值。 我实际上并不想回填数据。 combine_first首先从第一个数据帧中获取该值,如果丢失,它将尝试从第二个数据帧中获取该值。 因此,不满足条件2的缺失值将填充为零,否则将保持缺失。

关于以下内容的很多讨论:

df.sales = df.sales.combine_first(df.sales.bfill() * 0)

df.cum_sales = df.sales.cumsum()

print df

      quantity  sales  cum_sales
year                            
2010        10    0.0        0.0
2011        21   41.0       41.0
2012        20    0.0       41.0
2013        10    0.0       41.0
2014        39   32.0       73.0
2015        30    0.0       73.0
2016        31   31.0      104.0
2017        45    NaN        NaN
2018        23    NaN        NaN
2019        56    NaN        NaN

剧情:

df.plot()

在此处输入图片说明

因此,我认为最好在制作数据框之前先在字典中更改数据。 最佳方法是以相反的顺序遍历列表,忽略所有None值,直到满足第一个数值。 在那之后,所有None值都应更改为0

这不是解决此问题的最漂亮方法,但是它以易于阅读和理解的方式编写。 我相信这样会更好。

flag = False
for sale in data["sales"][::-1]:
    if !flag:
        if sale:
            flag = True
    else
        if !sale:
            sale = 0

更新: 您能否举一个例子,说明如何将您的解决方案实现为功能?

def set_col_last_valid(df, col, new_col):
    df.loc[(df.index <= df[col].last_valid_index()) & (pd.isnull(df[col])), col] = 0
    df[new_col] = df[col].cumsum()
    return df

In [174]: new = set_col_last_valid(df, 'sales', 'cum_sales')

In [175]: new
Out[175]:
      quantity  sales  cum_sales
year
2010        10    0.0        0.0
2011        21   41.0       41.0
2012        20    0.0       41.0
2013        10    0.0       41.0
2014        39   32.0       73.0
2015        30    0.0       73.0
2016        31   31.0      104.0
2017        45    NaN        NaN
2018        23    NaN        NaN
2019        56    NaN        NaN

原始答案:

您可以这样操作:

首先,将所有NaN设置为0 ,但末尾除外:

df.loc[(df.index <= df.sales.last_valid_index()) & (pd.isnull(df.sales)), 'sales'] = 0

现在您可以简单地使用cumsum()

In [142]: df.sales.cumsum()
Out[142]:
year
2010      0.0
2011     41.0
2012     41.0
2013     41.0
2014     73.0
2015     97.0
2016    128.0
2017      NaN
2018      NaN
2019      NaN
Name: sales, dtype: float64

说明:

In [154]: df.sales.last_valid_index()
Out[154]: 2016

In [155]: df.loc[df.index <= df.sales.last_valid_index()]
Out[155]:
      quantity  sales
year
2010        10    0.0
2011        21   41.0
2012        20    0.0
2013        10    0.0
2014        39   32.0
2015        30   24.0
2016        31   31.0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM