使用熊猫' TimeGrouper()以1秒的间隔查找列计数

时间:2017-11-21 05:49:50

标签: python pandas dataframe

考虑数据帧"数据"由Timestamp索引如下:

Index                                Receiver     Type         Retry
1970-01-01 00:00:00.000000000         R1          Data         1
1970-01-01 00:00:00.800000000         R1          Non-Data     1
1970-01-01 00:00:01.000287000         R2          Data         0
1970-01-01 00:00:01.600896000         R2          Data         1
1970-01-01 00:00:02.001388000         R1          Data         1
1970-01-01 00:00:02.004698000         R1          Non-Data     1
1970-01-01 00:00:02.006706000         R2          Data         1
1970-01-01 00:00:02.501351000         R2          Data         1
1970-01-01 00:00:02.810382000         R1          Data         0
1970-01-01 00:00:03.001981000         R1          Data         0
1970-01-01 00:00:03.377116000         R1          Data         0
1970-01-01 00:00:03.701811000         R2          Data         1
1970-01-01 00:00:03.910326000         R2          Data         0
1970-01-01 00:00:03.951355000         R2          Non-Data     1

我想找到Type为" Data"的所有行。和重试等于1,然后以1秒的间隔对索引进行分组,以查找每个接收器类型的计数。

所需输出为df2:

Index                        R1   R2
1970-01-01 00:00:00          1    0
1970-01-01 00:00:01          0    1
1970-01-01 00:00:02          1    2
1970-01-01 00:00:03          0    1

4 个答案:

答案 0 :(得分:3)

  

我最初设定赏金,因为我找不到时间来帮助OP,   但我能找到一些时间并提供4个选项,所有这些   解决OP的问题。我还清理了要删除的问题   冗余/陈旧信息,防止混淆。

选项1
使用query / eval / 布尔索引,过滤行,然后使用get_dummies + resample获取输出 -

df = df.query("Type == 'Data' and Retry == 1")\
      .set_index('Index').Receiver.str.get_dummies().resample('1S').sum()

df

                     R1  R2
Index                      
1970-01-01 00:00:00   1   0
1970-01-01 00:00:01   0   1
1970-01-01 00:00:02   1   2
1970-01-01 00:00:03   0   1

使用get_dummies + groupby -

的类似解决方案
df = df.query("Type == 'Data' and Retry == 1").set_index("Index")\
         .Receiver.str.get_dummies().groupby(pd.Grouper(freq='s')).sum()

df
                     R1  R2
Index                      
1970-01-01 00:00:00   1   0
1970-01-01 00:00:01   0   1
1970-01-01 00:00:02   1   2
1970-01-01 00:00:03   0   1

事实上,resamplegroupby + pd.Grouper几乎可以互换。

选项2
crosstab + resample -

i = df.query("Type == 'Data' and Retry == 1").set_index('Index').Receiver

df = pd.crosstab(i.index, i.values).resample('1S').sum()
df.index.name = df.columns.name = None

df
                     R1  R2                     
1970-01-01 00:00:00   1   0
1970-01-01 00:00:01   0   1
1970-01-01 00:00:02   1   2
1970-01-01 00:00:03   0   1

选项3
groupby + unstack(我认为这是最慢的一个) -

df = df.query("Type == 'Data' and Retry == 1")\
       .set_index('Index')\
       .groupby([pd.Grouper(freq='1S'), 'Receiver'])\
       .Receiver.count()\
       .unstack()\
       .fillna(0)

df

Receiver              R1   R2
Index                        
1970-01-01 00:00:00  1.0  0.0
1970-01-01 00:00:01  0.0  1.0
1970-01-01 00:00:02  1.0  2.0
1970-01-01 00:00:03  0.0  1.0

选项4

unstack + resample -

df = df.query("Type == 'Data' and Retry == 1")\
       .set_index(['Index', 'Receiver'])\
       .assign(foo=1)\
       .foo.unstack(-1)\
       .resample('s')\
       .sum()\
       .fillna(0)

df

Receiver              R1   R2
Index                        
1970-01-01 00:00:00  1.0  0.0
1970-01-01 00:00:01  0.0  1.0
1970-01-01 00:00:02  1.0  2.0
1970-01-01 00:00:03  0.0  1.0

答案 1 :(得分:3)

可以使用简单的pivot_table

来完成
ndf = df[df['Type'].eq('Data')].pivot_table(columns=['Receiver'],values='Retry',
             index=pd.Grouper(key='Index',freq='s'), aggfunc='sum',fill_value=0)

Receiver             R1  R2
Index                      
1970-01-01 00:00:00   1   0
1970-01-01 00:00:01   0   1
1970-01-01 00:00:02   1   2
1970-01-01 00:00:03   0   1

答案 2 :(得分:2)

方法1 - 屏蔽+重新采样

for r in ['R1','R2']:
    df['new'+r] = ((df.Type=='Data')&(df.Retry==1)&(df.Receiver==r)).astype(int)

df[['newR1','newR2']].resample('s').sum()

方法2 - 取消堆叠+重新取样

df=df[df.Type=='Data'].set_index('Receiver',append=True)
df['Retry'].unstack().resample('s').sum().fillna(0)

两种方法的结果基本相同,只有一些细微的格式差异(这是方法1的输出):

                     newR1  newR2
Index                            
1970-01-01 00:00:00      1      0
1970-01-01 00:00:01      0      1
1970-01-01 00:00:02      1      2
1970-01-01 00:00:03      0      1

快速讨论不同方法:在许多情况下,unstackpivot_table都可以用来完成类似的任务,就像在这种情况下一样。但pivot_table(如@ Dark的答案)在这种情况下看起来明显优越(但我会在此留下unstack答案仅用于比较目的。)

答案 3 :(得分:2)

我希望我在OP的问题中不会遗漏任何内容。我专注于最后一个示例数据,在" Last Edit"下给出。使用该数据,下面的代码产生所需的输出。

代码:

data = '' # <the OP's dataframe here>

def my_grouper(df):
    df = df[df['Type'] == 'Data']
    return df.groupby(['Receiver'])['Retry'].sum()


grouped_data = data.groupby(pd.Grouper(freq='1S')).apply(my_grouper)
grouped_data = pd.DataFrame(grouped_data).unstack(1).fillna(0)
grouped_data.columns = grouped_data.columns.droplevel(0)
print(grouped_data)

输出:

Receiver             R1  R2
Index                      
1970-01-01 00:00:00   1   0
1970-01-01 00:00:01   0   1
1970-01-01 00:00:02   1   2
1970-01-01 00:00:03   0   1