按周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 年

python pandas日期时间转换为日期

如何在 Seaborn distplot 中绘制 Pandas 日期时间序列?

熊猫从python中的日期字符串列获取日期值