识别连续的数据序列并计算其长度

时间:2016-09-02 23:03:27

标签: python function datetime pandas dataframe

我正在使用DataFrame,其中每个行观察都附加了一个序数日期时间对象。我编写了一个函数,我相信通过我的DataFrame查看,并使用以下代码识别这些连续发生的天数以及这些连续发生的日期的运行时间:

 def consecutiveCount(df):
    df= df.copy()
    cond1 = df['DATE_INT'].shift(-1) - df['DATE_INT'] == 1
    cond2 = df['DATE_INT'].shift(1) - df['DATE_INT'] == -1

    cond3 = df['DATE_INT'].shift(-2) - df['DATE_INT'] == 2            
    cond4 = df['DATE_INT'].shift(2) - df['DATE_INT'] == -2

现在我继续以同样的方式制定这些条件,直到这一点:

    cond55 = df['DATE_INT'].shift(-28) - df['DATE_INT'] == 28            
    cond56 = df['DATE_INT'].shift(28) - df['DATE_INT'] == -28

    cond57 = df['DATE_INT'].shift(-29) - df['DATE_INT'] == 29            
    cond58 = df['DATE_INT'].shift(29) - df['DATE_INT'] == -29

然后,我使用以下代码在列变量中写出'run'天数的长度:

    df.loc[cond1 | cond2, 'CONSECUTIVE_COUNT'] = 2
    df.loc[cond3 | cond4, 'CONSECUTIVE_COUNT'] = 3

我再继续,直到我达到30天的“跑步”。

    df.loc[cond55 | cond56, 'CONSECUTIVE_COUNT'] = 29
    df.loc[cond57 | cond58, 'CONSECUTIVE_COUNT'] = 30

最后,我将函数应用于我的DataFrame的特定组,如下所示:

    df1 = df.groupby(['COUNTY_GEOID_YEAR','TEMPBIN']).apply(consecutiveCount)

我确信有更有效的方法来编写此代码。我已经确定我的脚本中的瓶颈是通过在我的脚本中打印各种字符串来应用该功能。

以更有效的方式编写函数或如何加快应用函数的任何帮助都会很棒!如果我能提供更多信息,请告诉我。

编辑:正如@DSM所指出的那样,我的代码并没有准确地计算连续几天的长度。他的解决方案对我来说准确无误!

1 个答案:

答案 0 :(得分:1)

IIUC,您可以在应用groupby后使用shift-compare-cumsum模式,然后进行转换。

假设您的数据看起来像这样(简化了一点)

df = pd.DataFrame({"GEOID_YEAR": [2000]*10 + [2001]*4, "TEMPBIN": [1]*14,
                   "DATE_INT": [1,2,3,4,6,7,9,10,11,14] + list(range(14,18)),
                   "OTHER_COL": [2]*14})

    DATE_INT  GEOID_YEAR  OTHER_COL  TEMPBIN
0          1        2000          2        1
1          2        2000          2        1
2          3        2000          2        1
3          4        2000          2        1
4          6        2000          2        1
5          7        2000          2        1
6          9        2000          2        1
7         10        2000          2        1
8         11        2000          2        1
9         14        2000          2        1
10        14        2001          2        1
11        15        2001          2        1
12        16        2001          2        1
13        17        2001          2        1

然后

df["cons_id"] = df.groupby(["GEOID_YEAR", "TEMPBIN"])["DATE_INT"].apply(
    lambda x: (x != x.shift() + 1).cumsum())
df["cons_count"] = (df.groupby(["GEOID_YEAR", "TEMPBIN", "cons_id"])
                    ["cons_id"].transform("count"))

给我们

In [78]: df
Out[78]: 
    DATE_INT  GEOID_YEAR  OTHER_COL  TEMPBIN  cons_id  cons_count
0          1        2000          2        1        1           4
1          2        2000          2        1        1           4
2          3        2000          2        1        1           4
3          4        2000          2        1        1           4
4          6        2000          2        1        2           2
5          7        2000          2        1        2           2
6          9        2000          2        1        3           3
7         10        2000          2        1        3           3
8         11        2000          2        1        3           3
9         14        2000          2        1        4           1
10        14        2001          2        1        1           4
11        15        2001          2        1        1           4
12        16        2001          2        1        1           4
13        17        2001          2        1        1           4