在 Python Pandas 数据帧中计算 MRR
Calculate MRR in Python Pandas dataframe
我有一个包含以下列的 Pandas 数据框
date | months | price
我计算了一些基本的 BI 指标。我通过按日期对数据框进行分组并对价格求和来计算净收入:
df = df[["Date", "Price"]].groupby(df['Date'])["Price"].sum().reset_index()
现在,我想找到类似于净收入的 MRR,但如果列月份超过 1 个月,则价格应与接下来的月份相同 "moved"。而且,它是按月而不是日分组的。
例如,如果我在 2016 年 1 月,我有 3 个月的行,价格为 30 美元,我应该将 10 美元加到 1 月,10 美元到 2 月,10 美元到 3 月。
我的第一个想法是遍历数据框,跟踪月份和下个月我应该 "move" 的价格,然后手动创建一个新的数据框。
但是,首先,Pandas 中是否有任何 Pythonic 方法可以做到这一点?
重现数据帧的数据:
import pandas as pd
df = pd.DataFrame({'date': ['01-01-2016', '05-01-2016', '10-01-2016','04-02-2016'],
'months': [1, 3, 1, 6],
'price': [40, 60, 20, 60]})
想要的结果:
Date | MRR
January 2016 | 80
February 2016| 30
March 2016 | 10
April 2016 | 10
May 2016 | 10
June 2016 | 10
July 2016 | 10
每一行的结果都是这样计算的
January 2016 = 40 + 20 + 20 + 0
February 2016 = 0 + 20 + 0 + 10
March 2016 = 0 + 0 + 0 + 10
April 2016 = 0 + 0 + 0 + 10
May 2016 = 0 + 0 + 0 + 10
June 2016 = 0 + 0 + 0 + 10
July 2016 = 0 + 0 + 0 + 10
我不知道如何使用循环。但是,我可以建议一种使代码非常干净和高效的方法。
首先,让我们加载您在问题文本中提供的示例数据:
df = pd.DataFrame({'date': ['01-01-2016', '05-01-2016', '10-01-2016','04-02-2016'],
'months': [1, 3, 1, 6],
'price': [40, 60, 20, 60]})
为了使用 Panda 的日期功能(例如按月分组),我们将使用 date
列作为索引。 A DateTimeIndex
事实上:
df['date'] = pd.to_datetime(df['date'], format='%d-%m-%Y')
df = df.set_index('date')
现在,使用您已经知道但使用时间段的 resample function that works like the groupby 函数,例如查看逐月摘要真的很容易:
df.resample('M').sum()
现在到 "spread out" 行,其中 months
列在多个月内大于 1。我这里的方法是为每一行生成一个新的 DataFrame
:
dfs = []
for date, values in df.iterrows():
months, price = values
dfs.append(
pd.DataFrame(
# Compute the price for each month, and repeat this value
data={'price': [price / months] * months},
# The index is a date range for the requested number of months
index=pd.date_range(date, periods=months, freq='M')
)
)
现在我们可以连接 DataFrame
的列表,重新采样到月并求和:
pd.concat(dfs).resample('M').sum()
输出:
price
2016-01-31 80
2016-02-29 30
2016-03-31 30
2016-04-30 10
2016-05-31 10
2016-06-30 10
2016-07-31 10
请参阅 http://pandas.pydata.org/pandas-docs/stable/timeseries.html,了解 Panda 在时间方面可以做的所有很酷的事情。例如,要准确地产生您想要的输出,您可以这样做:
output.index = output.index.strftime('%B %Y')
结果是:
price
January 2016 80
February 2016 30
March 2016 30
April 2016 10
May 2016 10
June 2016 10
July 2016 10
我有一个包含以下列的 Pandas 数据框
date | months | price
我计算了一些基本的 BI 指标。我通过按日期对数据框进行分组并对价格求和来计算净收入:
df = df[["Date", "Price"]].groupby(df['Date'])["Price"].sum().reset_index()
现在,我想找到类似于净收入的 MRR,但如果列月份超过 1 个月,则价格应与接下来的月份相同 "moved"。而且,它是按月而不是日分组的。
例如,如果我在 2016 年 1 月,我有 3 个月的行,价格为 30 美元,我应该将 10 美元加到 1 月,10 美元到 2 月,10 美元到 3 月。
我的第一个想法是遍历数据框,跟踪月份和下个月我应该 "move" 的价格,然后手动创建一个新的数据框。
但是,首先,Pandas 中是否有任何 Pythonic 方法可以做到这一点?
重现数据帧的数据:
import pandas as pd
df = pd.DataFrame({'date': ['01-01-2016', '05-01-2016', '10-01-2016','04-02-2016'],
'months': [1, 3, 1, 6],
'price': [40, 60, 20, 60]})
想要的结果:
Date | MRR
January 2016 | 80
February 2016| 30
March 2016 | 10
April 2016 | 10
May 2016 | 10
June 2016 | 10
July 2016 | 10
每一行的结果都是这样计算的
January 2016 = 40 + 20 + 20 + 0
February 2016 = 0 + 20 + 0 + 10
March 2016 = 0 + 0 + 0 + 10
April 2016 = 0 + 0 + 0 + 10
May 2016 = 0 + 0 + 0 + 10
June 2016 = 0 + 0 + 0 + 10
July 2016 = 0 + 0 + 0 + 10
我不知道如何使用循环。但是,我可以建议一种使代码非常干净和高效的方法。
首先,让我们加载您在问题文本中提供的示例数据:
df = pd.DataFrame({'date': ['01-01-2016', '05-01-2016', '10-01-2016','04-02-2016'],
'months': [1, 3, 1, 6],
'price': [40, 60, 20, 60]})
为了使用 Panda 的日期功能(例如按月分组),我们将使用 date
列作为索引。 A DateTimeIndex
事实上:
df['date'] = pd.to_datetime(df['date'], format='%d-%m-%Y')
df = df.set_index('date')
现在,使用您已经知道但使用时间段的 resample function that works like the groupby 函数,例如查看逐月摘要真的很容易:
df.resample('M').sum()
现在到 "spread out" 行,其中 months
列在多个月内大于 1。我这里的方法是为每一行生成一个新的 DataFrame
:
dfs = []
for date, values in df.iterrows():
months, price = values
dfs.append(
pd.DataFrame(
# Compute the price for each month, and repeat this value
data={'price': [price / months] * months},
# The index is a date range for the requested number of months
index=pd.date_range(date, periods=months, freq='M')
)
)
现在我们可以连接 DataFrame
的列表,重新采样到月并求和:
pd.concat(dfs).resample('M').sum()
输出:
price
2016-01-31 80
2016-02-29 30
2016-03-31 30
2016-04-30 10
2016-05-31 10
2016-06-30 10
2016-07-31 10
请参阅 http://pandas.pydata.org/pandas-docs/stable/timeseries.html,了解 Panda 在时间方面可以做的所有很酷的事情。例如,要准确地产生您想要的输出,您可以这样做:
output.index = output.index.strftime('%B %Y')
结果是:
price
January 2016 80
February 2016 30
March 2016 30
April 2016 10
May 2016 10
June 2016 10
July 2016 10