Python-基于一百万行表上日期差的向量化条件变量和

Python-基于一百万行表上日期差的向量化条件变量和,python,pandas,Python,Pandas,我有以下数据帧: Date Variable 2018-04-10 21:05:00 a 2018-04-10 21:05:00 a 2018-04-10 21:10:00 b 2018-04-10 21:15:00 a 2018-04-10 21:35:00 b 2018-04-10 21:45:00 a

我有以下数据帧:

Date                         Variable
2018-04-10 21:05:00             a
2018-04-10 21:05:00             a
2018-04-10 21:10:00             b
2018-04-10 21:15:00             a
2018-04-10 21:35:00             b
2018-04-10 21:45:00             a
2018-04-10 21:45:00             a
我的目标是计算在30分钟之前和30分钟之后包含(
'a')
的行数 每次后分钟(包括前后时间相同的行) 之后,但不包括正在分析的每一行)。然后对每一个进行同样的操作
变量
。因此,对于
变量
a
,我的结论如下:

Date                   nr_30_min_bef_a    nr_30_min_after_a   
2018-04-10 21:05:00           1                    2                             
2018-04-10 21:05:00           1                    2
2018-04-10 21:10:00           2                    1
2018-04-10 21:15:00           2                    2
2018-04-10 21:35:00           3                    2
2018-04-10 21:45:00           2                    1
2018-04-10 21:45:00           2                    1
我曾尝试执行for循环来迭代所有行,问题是 整个系列有超过百万行,因此我正在寻找一个 有效的解决方案

import pandas as pd

df = pd.DataFrame({'Date': ['2018-04-10 21:05:00',
                            '2018-04-10 21:05:00',
                            '2018-04-10 21:10:00',
                            '2018-04-10 21:15:00',
                            '2018-04-10 21:35:00',
                            '2018-04-10 21:45:00',
                            '2018-04-10 21:45:00'],
                   'Variable': ['a', 'a', 'b', 'a', 'b', 'a', 'a']})
提前感谢。

在此基础上, 你可以用

import pandas as pd

df = pd.DataFrame({'Date': ['2018-04-10 21:05:00',
                            '2018-04-10 21:05:00',
                            '2018-04-10 21:10:00',
                            '2018-04-10 21:15:00',
                            '2018-04-10 21:35:00',
                            '2018-04-10 21:45:00',
                            '2018-04-10 21:45:00'],
                   'Variable': ['a', 'a', 'b', 'a', 'b', 'a', 'a']})

df['Date'] = pd.to_datetime(df['Date'])

freq_table = pd.crosstab(index=df['Date'], columns=df['Variable'])
df_bef = freq_table.rolling('30T', closed='both').sum().astype(int)
is_current = (freq_table != 0).astype(int)
df_bef -= is_current
df_bef.columns = ['nr_30_min_bef_{}'.format(col) for col in df_bef.columns]
result = pd.merge(df, df_bef, left_on='Date', right_index=True)

max_date = df['Date'].max()
min_date = df['Date'].min()
pseudo_dates = (max_date - df['Date'])[::-1] + min_date
freq_table_reversed = pd.crosstab(index=pseudo_dates, columns=df['Variable'])
df_after = freq_table_reversed.rolling('30T', closed='both').sum().astype(int)
df_after = pd.DataFrame(df_after.values[::-1], index=freq_table.index, 
                       columns=df_after.columns)
df_after -= is_current
df_after.columns = ['nr_30_min_after_{}'.format(col) for col in df_after.columns]

result = pd.merge(result, df_after, left_on='Date', right_index=True)
print(result)
哪张照片

                 Date Variable  nr_30_min_bef_a  nr_30_min_bef_b  nr_30_min_after_a  nr_30_min_after_b
0 2018-04-10 21:05:00        a                1                0                  2                  2
1 2018-04-10 21:05:00        a                1                0                  2                  2
2 2018-04-10 21:10:00        b                2                0                  1                  1
3 2018-04-10 21:15:00        a                2                1                  2                  1
4 2018-04-10 21:35:00        b                3                1                  2                  0
5 2018-04-10 21:45:00        a                2                1                  1                  0
6 2018-04-10 21:45:00        a                2                1                  1                  0

主要的新想法是使用
pd.crosstab
生成频率表:

freq_table = pd.crosstab(index=df['Date'], columns=df['Variable'])
# Variable             a  b
# Date                     
# 2018-04-10 21:05:00  2  0
# 2018-04-10 21:10:00  0  1
# 2018-04-10 21:15:00  1  0
# 2018-04-10 21:35:00  0  1
# 2018-04-10 21:45:00  2  0
然后对每个滚动窗口中的数字求和:

df_bef = freq_table.rolling('30T', closed='both').sum().astype(int)
由于您希望从计数中排除当前行,
is_current
df_bef
中减去:

is_current = (freq_table != 0).astype(int)
df_bef -= is_current

我用你评论中的信息修改了你的问题。请确认我没有改变你问题的意图。谢谢。但是这个方法在after列上给了我一个错误。例如,如果您将变量列上的最后一个字符串a替换为字符串b,并且如果您运行df['variable']=='b'的代码,则后面的列将给我一个-1数字。它不应该给出一个0数字吗(因为我们在30分钟的时间间隔内计算b的数量)?我添加了一个稍微不同的方法,它计算
变量中所有值的“before”和“after”。请参阅上面的编辑。如果我将上面发布的代码中的
df['Variable']=='a'
更改为
df['Variable']=='b'
,则我没有看到任何
-1
s。在使用实际的
df
时,您是否看到
-1
?如果是这样的话,你真实的
df
中可能有一些特殊的东西,我在我发布的代码中没有提到。在这种情况下,如果你能找出你真正的
df
与我现在看到的玩具有什么不同,那将非常有帮助。(一个生成-1的可运行示例将非常有用。)这种新方法非常有效。你绝对是个明星。非常感谢你。