具有 groupby 和滚动平均值的数据框行的累计数

Cumulative number of data frame rows with groupby and rolling average

作为我正在学习的课程的一部分,我需要计算每月火箭发射的累计总和并计算每月的滚动平均值,最后在绘图上显示这两个结果。

数据帧包含DateLaunch siteMission status和其他一些不太重要的参数。日期格式为YYYY-MM-DD,不同年月组合的项目数不同。

输入数据如下所示:

Organisation    Location    Date    Detail  Rocket_Status   Price   Mission_Status
4323    RVSN USSR   Site 1/5, Baikonur Cosmodrome, Kazakhstan   1957-10-04 19:28:00+00:00   Sputnik 8K71PS | Sputnik-1  StatusRetired   63.23   Success
4322    RVSN USSR   Site 1/5, Baikonur Cosmodrome, Kazakhstan   1957-11-03 02:30:00+00:00   Sputnik 8K71PS | Sputnik-2  StatusRetired   63.23   Success
4321    US Navy LC-18A, Cape Canaveral AFS, Florida, USA    1957-12-06 16:44:00+00:00   Vanguard | Vanguard TV3 StatusRetired   63.23   Failure

我的做法是:

launchdays = pd.DataFrame(spacerace.groupby(spacerace.loc[:,"Date"].dt.date).agg("size"))

此数据框包含以下数据:

            0
Date    
1957-10-04  1
1957-11-03  1
1957-12-06  1
1958-02-01  1
1958-02-05  1
launchdays.index = pd.to_datetime(launchdays.index)
monthly_data = launchdays.resample("M").sum()
rolling = launchdays.rolling(30).mean().dropna()

重采样后的每月数据:

            0
Date    
1957-10-31  1
1957-11-30  1
1957-12-31  1
1958-01-31  0
1958-02-28  2

滚动平均值:

            0
Date    
1958-12-18  1.03
1959-01-02  1.03
1959-02-17  1.03
1959-02-28  1.03
1959-04-13  1.03

这似乎可行,并且输出至少在我看来是真实的 — 但是,我想确定我的方法是否正确 and/or 是否可以更优雅地完成此操作。

谢谢!


另一个编辑:

我已经修复了收集每月数据和计算滚动平均值的部分:

monthly_data = launchdays.resample("30D").sum()
rolling = monthly_data.rolling(“30D").mean()

但是,它们现在都产生完全相同的输出,这是意料之中的......也许我误解了这个练习的某些内容?此任务定义为:“绘制直到现在为止的每月发射次数图表。哪个月份的发射次数最多?在月份时间序列上叠加月份的滚动平均值图表。”

我不知道我是否理解你的实际问题,我不喜欢争论优雅与不优雅的解决方案。如果他们工作,他们是好的。另一个解决方案是否更好取决于您比较同一问题的不同解决方案的方式,例如需要更少的时间、更少的内存或更少的代码行等。

回到您的问题,滚动平均值和重采样总和之间存在差异。 滚动平均值是一种平滑数据以提供正确趋势的方法,请参阅 https://en.wikipedia.org/wiki/Moving_average. In contrast, the resample and sum method is a data aggregation on binned data, basically a histogram https://en.wikipedia.org/wiki/Histogram

所以如果问题是哪个月的发布次数最多,你需要计算直方图并找到最大值。

您练习中的滚动平均值部分定义不明确,因为它没有给出 window 大小,或者至少提供了更多信息,说明为什么您应该对数据进行平滑处理。肯定要超过30天,因为有超过30天的月份。我猜他们的意思是一年(12 个月)window,但这纯粹是猜测。

编辑:我认为他们的意思是这样的:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

np.random.seed(7)
pd.plotting.register_matplotlib_converters()

# create dummy data
dates = (
    pd.Timestamp('1970-01-01') +
    pd.to_timedelta(np.random.randint(0, 19000, 20000), unit='D')
)
success = np.random.random(len(dates)) > 0.05
df = pd.DataFrame({
    'date': dates,
    'success': success
})
df.sort_values('date', inplace=True)
df.reset_index(drop=True, inplace=True)

# create histogram
monthly = df['date'].groupby(
    df['date'].dt.to_period('M').dt.to_timestamp()
).count()
print(monthly.loc[monthly==monthly.max()])

# add zeros for months that do not appear in the original histogram
monthly_dense = monthly.resample('MS').sum()

# plot
fig, ax = plt.subplots()
ax.plot(monthly_dense.index, monthly_dense)
ax.plot(monthly_dense.index, monthly_dense.rolling(12).mean())
fig.autofmt_xdate()