【问题标题】:Grouping a range of dates in Python在 Python 中对日期范围进行分组
【发布时间】:2016-01-09 04:26:09
【问题描述】:

我有以下数据库,我想将 PAS_DATE 分组为 3 天,例如从 2015-03-06 到 2015-03-09

PAS_DATE    RED_DATE       TOT
2015-03-06  2015-03-07     2
            2015-03-17    14
            2015-12-22     1
2015-03-07  2015-03-08     3
            2015-03-19     6
            2015-10-14     2
            2015-12-07     1
2015-03-08  2015-09-16     8
2015-03-09  2015-03-09     7
            2015-03-15     6
            2015-03-18     8
            2015-04-04    15
            2015-04-12    19
            2015-05-04    44
            2015-08-17     5
            2015-09-09    13
            2015-12-06     3
            2015-12-13     3
2015-03-10  2015-03-10     7

输出应该是:

PAS_DATE    RED_DATE      TOT
2015-03-09  2015-03-07     2
            2015-03-17    14
            2015-12-22     1
            2015-03-08     3
            2015-03-19     6
            2015-10-14     2
            2015-12-07     1
            2015-09-16     8
            2015-03-09     7
            2015-03-15     6
            2015-03-18     8
            2015-04-04    15
            2015-04-12    19
            2015-05-04    44
            2015-08-17     5
            2015-09-09    13
            2015-12-06     3
            2015-12-13     3
2015-03-12  2015-03-10     7

有没有办法在 Pandas 或 Python 中执行此代码而无需迭代?

【问题讨论】:

  • 没有迭代?你的意思是根本没有任何循环结构?
  • 是的,我有一个大数据集,循环结构很慢......
  • 一种或另一种方式,您将不得不迭代行来评估数据。循环是任何在集合或编程中工作的核心构造之一。
  • 我已经尝试了你有趣的解决方案,但我得到了 df['for_group_by'] = df.PAS_DATE + df['shift'] 的 ITypeError: ufunc add cannot use operands with types dtype('O')和 dtype('
  • 我已经更新了我原来的答案。

标签: python python-2.7 python-3.x pandas


【解决方案1】:

我不知道,这是否比使用带有 iterrows() 的循环更有效,但这里有一种方法(不过,它很老套):

df = pd.DataFrame(pd.date_range("2015-01-01","2015-01-10"), columns=['PAS_DATE'])

df['dt_since_first'] = (df.PAS_DATE - df.PAS_DATE.min()).dt.days
df['shift'] = pd.to_timedelta(2 - np.mod(df.dt_since_first, 3), unit='d')
df['for_group_by'] = df.PAS_DATE + df['shift']
  1. 创建一个新列,其中包含 自列中第一个日期以来的 timedelta 并将其转换为 整数,以天数表示。
  2. 现在使用 mod3 来查找,PAS_DATE 必须移动多少天才能得到 到您的 3 天 (ceil) 分箱并将其转换回 timedelta 对象。
  3. 只需将 PAS_DATE 移动这个 timedelta。

这是输出:

    PAS_DATE  dt_since_first  shift for_group_by
0 2015-01-01               0 2 days   2015-01-03
1 2015-01-02               1 1 days   2015-01-03
2 2015-01-03               2 0 days   2015-01-03
3 2015-01-04               3 2 days   2015-01-06
4 2015-01-05               4 1 days   2015-01-06
5 2015-01-06               5 0 days   2015-01-06
6 2015-01-07               6 2 days   2015-01-09
7 2015-01-08               7 1 days   2015-01-09
8 2015-01-09               8 0 days   2015-01-09
9 2015-01-10               9 2 days   2015-01-12

您可以在同一列上迭代地执行此操作,我只是为每个步骤使用不同的列以便于理解...

编辑评论

我猜,您的 PAS_DATE 列属于 dtype=object,尽管您的条目属于 dtype=np.datetime[64]。有一些强有力的理由,为什么应该避免这种情况。

我曾经在很长的 DataFrame 中遇到过这种情况,直到我弄明白我经历了地狱。有各种各样的例外,我在 Stackoverflow 上花了无数时间试图解决我的问题。此外,一切都非常缓慢,最重要的是,保存 df 的内存需求非常大。

发生了什么事。您的列是 dtype=object,这意味着它只包含指向大量日期时间对象的指针。如果它是 dtype=np.datetime[64],它只会保存 64 位的日期时间信息。

尝试查看信息,它应该如下所示:

print df.info()

Output:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 10 entries, 0 to 9
Data columns (total 4 columns):
PAS_DATE          10 non-null datetime64[ns]
dt_since_first    10 non-null int64
shift             10 non-null timedelta64[ns]
for_group_by      10 non-null datetime64[ns]
dtypes: datetime64[ns](2), int64(1), timedelta64[ns](1)
memory usage: 400.0 bytes

现在要转换您的 PAS_DATE 列,请尝试以下方法:

df.PAS_DATE = df.PAS_DATE.convert_objects(convert_dates='coerce')

顺便说一句,您应该尽快在您的代码中执行此操作。并且可能也应该对您的其他日期列执行此操作。在转换前后执行 df.info() 。告诉我们,内存使用量的区别是什么。

【讨论】:

  • 这不是您的代码的问题。 Panda's 是处理此类事情的好方法,但它仍在迭代。迭代现在在 pandas 包中完成,以便将数据映射到索引数据帧中。 “没有迭代”的想法从根本上是有缺陷的。在某些时候,必须将数据集拆分为行,并且必须以某种方式评估每一行,无论是通过它们的实际内容还是通过它们相对于其他行的元数据。
  • @tlastowka 你是对的,当然。仅仅因为多次执行相同的操作(字面意思是 for each 行),肯定会有循环。实际上有几个,因为我的代码需要在数据帧上迭代多次。尽管如此,这现在是矢量化的,并且 numpy 正在以高度优化的方式进行操作。我想它更快,但也需要更多内存。
猜你喜欢
  • 2023-01-28
  • 2013-01-28
  • 2016-12-08
  • 1970-01-01
  • 2014-04-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-13
  • 2019-02-19
相关资源
最近更新 更多