【问题标题】:count jumps from one location to another based on conditions根据条件计数从一个位置跳转到另一个位置
【发布时间】:2019-02-28 01:56:17
【问题描述】:

我有以下数据框。

    id  start   finish  location
0   1   2015-12-14 16:44:00 2015-12-15 18:00:00 A
1   1   2015-12-15 18:00:00 2015-12-16 13:00:00 B
2   1   2015-12-16 13:00:00 2015-12-16 20:00:00 C
3   2   2015-12-10 13:15:00 2015-12-12 13:45:00 B
4   2   2015-12-12 13:45:00 2015-12-12 19:45:00 A
5   3   2015-12-15 07:45:00 2015-12-15 18:45:00 A
6   3   2015-12-15 18:45:00 2015-12-18 07:15:00 D
7   3   2015-12-18 07:15:00 2015-12-19 10:45:00 C
8   3   2015-12-19 10:45:00 2015-12-20 09:00:00 H
9   4   2015-12-09 10:45:00 2015-12-13 12:20:00 E
10  4   2015-12-13 12:20:00 2015-12-13 18:20:00 A
11  4   2015-12-13 18:20:00 2015-12-13 23:40:00 A
12  4   2015-12-13 23:40:00 2015-12-16 08:00:00 B
13  5   2015-12-07 08:00:00 2015-12-13 12:25:00 H

我想计算每个“id”中从一个位置到另一个位置的跳转。对于这些跳转计数,首先我想将完成列的日期和时间与相同 id 的下一行的开始列的日期和时间进行比较。如果匹配,我希望计数为 1,否则为 0。我想要获得的是以下内容:

    id  start   count
0   1   2015-12-14 16:44:00 1
1   1   2015-12-15 18:00:00 1
2   1   2015-12-16 13:00:00 0
3   2   2015-12-10 13:15:00 1
4   2   2015-12-12 13:45:00 0
5   3   2015-12-15 07:45:00 1
6   3   2015-12-15 18:45:00 1
7   3   2015-12-18 07:15:00 1
8   3   2015-12-19 10:45:00 0
9   4   2015-12-09 10:45:00 1
10  4   2015-12-13 12:20:00 1
11  4   2015-12-13 18:20:00 1
12  4   2015-12-13 23:40:00 0
13  5   2015-12-07 08:00:00 0

一旦我有了这个,我想根据日期对计数求和以获得类似以下的结果:

date    count_sum
2015-12-07  0
2015-12-09  1
2015-12-10  1
2015-12-12  0
2015-12-13  2
2015-12-14  1
2015-12-15  3
2015-12-16  0
2015-12-18  1
2015-12-19  0

对我来说,最后一部分很容易通过根据日期执行 groupby() 并使用 .sum() 来总结该日期的所有计数。但是如何获得我们计算实际跳跃的第一部分尚不清楚。任何帮助将不胜感激。

【问题讨论】:

    标签: pandas python-3.5 pandas-groupby


    【解决方案1】:

    您的数据似乎已按'start' 排序,因此您只需groupby 并检查完成时间是否与pandas.Series.shift() 下一行的开始时间相同

    我建议不要调用列 'count',因为这是 pandas 的内置函数,因此您不能使用 Series.col_name 表示法。

    #df['start'] = pd.to_datetime(df.start)
    #df['finish'] = pd.to_datetime(df.finish)
    df['count'] = (df.groupby('id').apply(lambda x: x.finish == x.start.shift(-1))
                     .astype('int').reset_index(level=0, drop=True))
    

    输出:

        id               start              finish location  count
    0    1 2015-12-14 16:44:00 2015-12-15 18:00:00        A      1
    1    1 2015-12-15 18:00:00 2015-12-16 13:00:00        B      1
    2    1 2015-12-16 13:00:00 2015-12-16 20:00:00        C      0
    3    2 2015-12-10 13:15:00 2015-12-12 13:45:00        B      1
    4    2 2015-12-12 13:45:00 2015-12-12 19:45:00        A      0
    5    3 2015-12-15 07:45:00 2015-12-15 18:45:00        A      1
    6    3 2015-12-15 18:45:00 2015-12-18 07:15:00        D      1
    7    3 2015-12-18 07:15:00 2015-12-19 10:45:00        C      1
    8    3 2015-12-19 10:45:00 2015-12-20 09:00:00        H      0
    9    4 2015-12-09 10:45:00 2015-12-13 12:20:00        E      1
    10   4 2015-12-13 12:20:00 2015-12-13 18:20:00        A      1
    11   4 2015-12-13 18:20:00 2015-12-13 23:40:00        A      1
    12   4 2015-12-13 23:40:00 2015-12-16 08:00:00        B      0
    13   5 2015-12-07 08:00:00 2015-12-13 12:25:00        H      0
    

    为了完整性:

    df.groupby(df.start.dt.date)['count'].sum()
    start
    2015-12-07    0
    2015-12-09    1
    2015-12-10    1
    2015-12-12    0
    2015-12-13    2
    2015-12-14    1
    2015-12-15    3
    2015-12-16    0
    2015-12-18    1
    2015-12-19    0
    

    【讨论】:

    • 哇,太好了!我猜你要么想确保df['id, 'start'] 上排序,要么在groupby 之后使用.sort_index,这样它就不会与行顺序混淆?
    • 嗨,Alollz,非常感谢。结果很完美。是的,数据框已经根据 id 和 start 进行了排序。感谢您的建议。我不知道使用列名“count”可能会出现问题。从现在开始,我将避免使用“count”作为列名。
    • 虽然您的代码运行良好,但我不明白您的代码中的 lambda 函数如何在满足条件时返回 1,否则返回 0。你能解释一下你是如何在计数列中得到 1 和 0 的吗?提前致谢。
    • @HT121,如果结束值等于下一行的开始值(移位完成与下一行的比较),则 lambda 函数返回TrueFalse。然后你会得到10,因为我使用了.astype('int'),这会将True 转换为1False0
    猜你喜欢
    • 2016-01-07
    • 2014-11-25
    • 2019-12-27
    • 2017-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多