按周python迭代带有日期列的pd df
Posted
技术标签:
【中文标题】按周python迭代带有日期列的pd df【英文标题】:Iterate over pd df with date column by week python 【发布时间】:2019-01-15 22:03:21 【问题描述】:我有一个一个月的 DataFrame,其中包含一个日期时间对象列和一堆我想应用到它的函数 - 按周。所以我想循环遍历 DataFrame 并将函数应用于每周。如何迭代每周的时间段?
我的 DataFrame 如下所示:
这是一些随机的日期时间代码:
np.random.seed(123)
n = 500
df = pd.DataFrame(
'date':pd.to_datetime(
pd.DataFrame( 'year': np.random.choice(range(2017,2019), size=n),
'month': np.random.choice(range(1,2), size=n),
'day': np.random.choice(range(1,28), size=n)
)
)
)
df['random_num'] = np.random.choice(range(0,1000), size=n)
我的周长不一致(有时我每周有 1000 条推文,有时是 100,000 条)。请有人给我一个如何按周循环这个数据框的例子吗? (我不需要聚合或 groupby 函数。)
【问题讨论】:
groupby
是一种很好的方式(即使您确实想循环)通过生成的 DF 访问组中的数据。您能否详细说明为什么不需要它们/聚合函数?当有人说这就是他们想要的东西时,总是有点“嗯……你真的,真的确定吗”……
当然。我将 NLP 函数应用于推文,然后对它们进行聚类。我有 6 个月的数据,并决定为每个月进行 k 均值聚类(每周进行一次太耗时)。现在我想将使用该 k 的聚类应用到每个星期,这样我就可以对每周的 twitter 数据进行聚类。现在清楚了吗?
如果您的时间戳是一个时间戳,您可以使用for k, g in df.groupby(pd.Grouper(key='timestamp', freq='W'))
,其中k
将是一周,g
将是DataFrame
那一周的项目...?跨度>
【参考方案1】:
如果你真的不想使用 groupby 和聚合,那么:
for week in df['date'].dt.week.unique():
this_weeks_data = df[df['date'].dt.week == week]
如果您有超过一年的数据,这当然会出错。
【讨论】:
工作正常!这样我就可以将所有函数和聚类应用于每周数据。【参考方案2】:给定您的示例数据框
date random_num
0 2017-01-01 214
1 2018-01-19 655
2 2017-01-24 663
3 2017-01-26 723
4 2017-01-01 974
首先,您可以尝试将索引设置为日期时间对象,如下所示
df.set_index(df.date, inplace=True)
df.drop('date', axis=1, inplace=True)
这会将索引设置为日期列并删除原始列。你会得到
>>> df.head()
date random_num
2017-01-01 214
2018-01-19 655
2017-01-24 663
2017-01-26 723
2017-01-01 974
然后您可以使用 pandas groupby
函数根据您的频率对数据进行分组,并应用您选择的任何函数。
# To group by week and count the number of occurances
>>> df.groupby(pd.Grouper(freq='W')).count().head()
date random_num
2017-01-01 11
2017-01-08 65
2017-01-15 55
2017-01-22 66
2017-01-29 45
# To group by week and sum the random numbers per week
>>> df.groupby(pd.Grouper(freq='W')).sum().head()
date random_num
2017-01-01 7132
2017-01-08 33916
2017-01-15 31028
2017-01-22 31509
2017-01-29 22129
您还可以使用 pandas 的 apply
方法应用任何泛型函数 myFunction
df.groupby(pd.Grouper(freq='W')).apply(myFunction)
如果您想在分组后将函数myFunction
应用于任何特定列columnName
,您也可以这样做
df.groupby(pd.Grouper(freq='W'))[columnName].apply(myFunction)
【讨论】:
【参考方案3】:[解决了多年]
pd.Grouper(freq='W')
工作正常,但有时我会遇到一些不受欢迎的行为,这些行为与当周数不均匀时如何拆分周数有关。所以这就是为什么我有时更喜欢像本例所示那样手动拆分一周。
因此,拥有一个跨越多年的数据集
import numpy as np
import pandas as pd
import datetime
# Create dataset
np.random.seed(123)
n = 100000
date = pd.to_datetime(
'year': np.random.choice(range(2017, 2020), size=n),
'month': np.random.choice(range(1, 13), size=n),
'day': np.random.choice(range(1, 28), size=n)
)
random_num = np.random.choice(
range(0, 1000),
size=n)
df = pd.DataFrame('date': date, 'random_num': random_num)
如:
print(df.head())
date random_num
0 2019-12-11 413
1 2018-06-08 594
2 2019-08-06 983
3 2019-10-11 73
4 2017-09-19 32
首先创建一个允许您按周迭代的辅助索引(也考虑到年份):
df['grp_idx'] = df['date'].apply(
lambda x: '%s-%s' % (x.year, ':02d'.format(x.week)))
print(df.head())
date random_num grp_idx
0 2019-12-11 413 2019-50
1 2018-06-08 594 2018-23
2 2019-08-06 983 2019-32
3 2019-10-11 73 2019-41
4 2017-09-19 32 2017-38
然后只需应用对每周子集进行计算的函数,如下所示:
def something_to_do_by_week(week_data):
"""
Computes the mean random value.
"""
return week_data['random_num'].mean()
weekly_mean = df.groupby('grp_idx').apply(something_to_do_by_week)
print(weekly_mean.head())
grp_idx
2017-01 515.875668
2017-02 487.226704
2017-03 503.371681
2017-04 497.717647
2017-05 475.323420
获得每周指标后,您可能希望返回比年周指标更有用的实际日期:
def from_year_week_to_date(year_week):
"""
"""
year, week = year_week.split('-')
year, week = int(year), int(week)
date = pd.to_datetime('%s-01-01' % year)
date += datetime.timedelta(days=week * 7)
return date
weekly_mean.index = [from_year_week_to_date(x) for x in weekly_mean.index]
print(weekly_mean.head())
2017-01-08 515.875668
2017-01-15 487.226704
2017-01-22 503.371681
2017-01-29 497.717647
2017-02-05 475.323420
dtype: float64
最后,现在您可以绘制带有可解释日期的精美图:
作为一个健全的检查,使用pd.Grouper(freq='W')
的计算给了我几乎相同的结果(不知何故,它在 pd.Series 的开头增加了一个额外的一周)
df.set_index('date').groupby(
pd.Grouper(freq='W')
).mean().head()
Out[27]:
random_num
date
2017-01-01 532.736364
2017-01-08 515.875668
2017-01-15 487.226704
2017-01-22 503.371681
2017-01-29 497.717647
【讨论】:
以上是关于按周python迭代带有日期列的pd df的主要内容,如果未能解决你的问题,请参考以下文章
python - 如何将带有年份的周数转换为python pandas中的日期时间格式?
带有日期列表的 Pyspark DF(使用 PANDAS)从今天开始 BACK 1 年