python - 在 Python 中对一系列日期进行分组

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

我有以下数据库,我想将 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 中执行此代码而无需迭代?

最佳答案

我不知道,这是否比使用带有 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。

这是输出:

    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,我自己曾经遇到过这种情况,直到我弄清楚它,我才经历了 hell 。有各种各样的异常(exception),我在 Stackoverflow 上花了无数时间试图解决我的问题。此外,一切都非常缓慢,最重要的是,保存 df 的内存需求非常大。

这是怎么回事。您的列是 dtype=object,这意味着它只包含指向大量 datetime 对象的指针。如果它是 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()。告诉我们,内存使用量之间的区别是什么。

关于python - 在 Python 中对一系列日期进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33068463/

相关文章:

python 字典和函数不起作用

python - 带有漏洞的 Matplotlib 补丁

python - 到整数方格上的位置的距离

python - MYSQL: "Access denied for user ' X' @'localhost' (using password: YES)"PYTHON

python - 执行逻辑运算并同时添加数据帧的新列?

python - Django NoReverseMatch

Python:如何将 2.7 模块导入 3.4 程序?

python-3.x - 无法从 OpenGL_accelerate 加载 numpy_formathandler 加速器

python - 导入错误没有名为 '_sqlite3' python3.4 的模块

python - 我如何使用 Python 字符串以使相同的代码在 2.6、2.7、3.x 中工作