如何计算一列的累积和并创建一个新列?
Posted
技术标签:
【中文标题】如何计算一列的累积和并创建一个新列?【英文标题】:How to calculate the cumulative sum of a column and create a new column? 【发布时间】:2021-11-08 00:30:58 【问题描述】:我有一个 pyspark 数据框:
Location Month Brand Sector TrueValue PickoutValue
USA 1/1/2021 brand1 cars1 7418 30000
USA 2/1/2021 brand1 cars1 1940 2000
USA 3/1/2021 brand1 cars1 4692 2900
USA 4/1/2021 brand1 cars1
USA 1/1/2021 brand2 cars2 16383104.2 16666667
USA 2/1/2021 brand2 cars2 26812874.2 16666667
USA 3/1/2021 brand2 cars2
USA 1/1/2021 brand3 cars3 75.6% 70.0%
USA 3/1/2021 brand3 cars3 73.1% 70.0%
USA 2/1/2021 brand3 cars3 77.1% 70.0%
每个品牌的月份值从 2021 年 1 月 1 日到 2021 年 12 月 1 日。我需要创建另一个列,其中包含基于品牌和部门以及按月排序的 TrueValue 列的累积总和。 具有 % 值的行应该是累积总和除以月数。
我预期的数据框是:
Location Month Brand Sector TrueValue PickoutValue TotalSumValue
USA 1/1/2021 brand1 cars1 7418 30000 7418
USA 2/1/2021 brand1 cars1 1940 2000 9358
USA 3/1/2021 brand1 cars1 4692 2900 14050
USA 4/1/2021 brand1 cars1 14050
USA 1/1/2021 brand2 cars2 16383104.2 16666667 16383104.2
USA 2/1/2021 brand2 cars2 26812874.2 16666667 43195978.4
USA 3/1/2021 brand2 cars2 43195978.4
USA 1/1/2021 brand3 cars3 75.6% 70.0% 75.6%
USA 3/1/2021 brand3 cars3 73.1% 70.0% 76.3%
USA 2/1/2021 brand3 cars3 77.1% 70.0% 75.3%
对于具有 % 值的行,这就是我需要计算累积总和的方式按月排序:
(75.6 + 0)/1 = 75.6%
(75.6 + 77.1)/2 = 76.3%
(75.6 + 77.1 + 73.1)/3 = 75.3%
我能够生成累积总和,但我没有得到 % 值的累积总和。
这是我的代码块:
df=df.withColumn("month_in_timestamp", to_timestamp(df.Month, 'dd/MM/yyyy'))
windowval = (Window.partitionBy('Brand','Sector').orderBy('Month')
.rangeBetween(Window.unboundedPreceding, 0))
df1 = df1.withColumn('TotalSumValue', F.sum('TrueValue').over(windowval))
【问题讨论】:
你能解释清楚TotalSumValue
是如何计算的吗?\
这能回答你的问题吗? Pandas groupby cumulative sum
TotalSumValue
由 TrueValue 列值的累积和计算得出。例如:对于 1 月,我需要 TotalSumValue
中来自 TrueValue
列的相同值,即 7418。对于下一个值,Jan + Feb 即 7418+1940=9358 等等。
【参考方案1】:
似乎带有 % 的值的计算是累积平均计算。如果是这样,您可以为不包含%
的值应用累积总和,为具有%
的值应用累积平均值(在计算之前先删除百分号)。您可以使用when
-otherwise
来应用这两种计算。
import pyspark.sql.functions as F
from pyspark.sql.window import Window
df = df.withColumn("month_in_timestamp", F.to_timestamp(F.col("Month"), 'dd/MM/yyyy'))
# use 'month_in_timestamp' instead of 'month'
windowval = (Window.partitionBy('Brand','Sector').orderBy('month_in_timestamp')
.rangeBetween(Window.unboundedPreceding, 0))
df = df.withColumn("TotalSumValue",
F.when(F.col("TrueValue").contains("%"),
F.concat(F.avg(F.expr("replace(TrueValue, '%', '')")).over(windowval).cast("decimal(4,1)"), F.lit("%")))
.otherwise(F.sum('TrueValue').over(windowval).cast("decimal(13,1)")))
df.show()
# +--------+--------+------+------+----------+------------+-------------------+-------------+
# |Location| Month| Brand|Sector| TrueValue|PickoutValue| month_in_timestamp|TotalSumValue|
# +--------+--------+------+------+----------+------------+-------------------+-------------+
# | USA|1/1/2021|brand1| cars1| 7418| 30000|2021-01-01 00:00:00| 7418.0|
# | USA|2/1/2021|brand1| cars1| 1940| 2000|2021-01-02 00:00:00| 9358.0|
# | USA|3/1/2021|brand1| cars1| 4692| 2900|2021-01-03 00:00:00| 14050.0|
# | USA|4/1/2021|brand1| cars1| null| null|2021-01-04 00:00:00| 14050.0|
# | USA|1/1/2021|brand2| cars2|16383104.2| 16666667|2021-01-01 00:00:00| 16383104.2|
# | USA|2/1/2021|brand2| cars2|26812874.2| 16666667|2021-01-02 00:00:00| 43195978.4|
# | USA|3/1/2021|brand2| cars2| null| null|2021-01-03 00:00:00| 43195978.4|
# | USA|1/1/2021|brand3| cars3| 75.6%| 70.0%|2021-01-01 00:00:00| 75.6%|
# | USA|2/1/2021|brand3| cars3| 77.1%| 70.0%|2021-01-02 00:00:00| 76.4%|
# | USA|3/1/2021|brand3| cars3| 73.1%| 70.0%|2021-01-03 00:00:00| 75.3%|
# +--------+--------+------+------+----------+------------+-------------------+-------------+
【讨论】:
谢谢!!这有帮助:)以上是关于如何计算一列的累积和并创建一个新列?的主要内容,如果未能解决你的问题,请参考以下文章
rollapplyr()仅创建一个新列,而不为.SDcols中的每一列创建多个列