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

Python 使用熊猫';TimeGrouper()以1秒为间隔查找列计数,python,pandas,dataframe,Python,Pandas,Dataframe,考虑按时间戳索引的数据帧“数据”,如下所示: 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.00028700

考虑按时间戳索引的数据帧“数据”,如下所示:

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
我希望找到类型为“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
我最初设定的悬赏是因为我没有时间帮助OP, 但我能找到一些时间,并提供4个选项,所有这些 回答OP的问题。我还清理了要删除的问题 冗余/陈旧信息,防止混淆

选项1
使用
query
/
eval
/布尔索引,筛选行,然后使用
get\u dummies
+
重采样
获取输出-

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
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
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
事实上,
resample
groupby
+
pd.Grouper
是非常可互换的操作


选项2
交叉表
+
重采样
-

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
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
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

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


选项4

取消堆叠
+
重新采样
-

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
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
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——掩蔽+重采样

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()
df=df[df.Type=='Data'].set_index('Receiver',append=True)
df['Retry'].unstack().resample('s').sum().fillna(0)
方法2——取消堆叠+重新采样

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()
df=df[df.Type=='Data'].set_index('Receiver',append=True)
df['Retry'].unstack().resample('s').sum().fillna(0)
两种方法的结果基本相同,但格式有一些细微差异(这是方法1的输出):


快速讨论不同的方法:在许多情况下,
unstack
pivot_table
都可以用于完成类似的任务,如本例所示。但是在这种情况下,
pivot\u table
(如@Dark的答案)显然更优越(但我将把我的
unstack
答案放在这里仅供比较)。

我希望我没有遗漏OP问题中的任何内容。我将重点放在“最后一次编辑”下给出的最后一个示例数据上。使用这些数据,下面的代码生成所需的输出

代码:


它可以通过一个简单的
pivot\u表来完成,即

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

嗨@cᴏʟᴅsᴘᴇᴇᴅ, 在上述相同的解决方案(第二种方法)中,基于这两个条件,如果我想返回“01”,如果列“Retry”仅包含“0”,则返回“10”,如果“Retry”仅包含“1”和“11”,如果“Retry”同时包含“0”和“1”。所有计算应按照规定的“1S”频率进行。。。。。。。。。。。谢谢,[Asif]请注意,我尝试了使用“面具”的第二种方法,但它给出了错误的计数。第一种方法很好。我通过在MS Excel中应用过滤器进行了验证。亲爱的@cᴏʟᴅsᴘᴇᴇᴅ, 在上面的解决方案中,使用第二种方法使用“掩码”,在应用于我的原始大df时,给出了错误的计数。我使用MS Excel中的过滤器验证了结果。第一种方法提供了正确的计数,但正如您所说,它“完全删除了不满足您的条件的行”,这在y情况下是不需要的。如果有什么遗漏,请看第二种方法。@MuhammadAsifKhan我没有时间帮助你,所以我悬赏了你的问题。祝你好运。:)赏金。。。哇!非常感谢。我不知道堆栈溢出的这些特性。这是一个非常有趣的平台。那么给定数据的预期输出是什么呢?正如@Bharath所问的,如果您能够显示所需的输出,就更容易理解了。它也可能有助于使示例数据稍微大一些(10行左右?)显示coldspeed的代码很好,但我们并不需要它,因为我们可以在下面看到它,我也不知道coldspeed的代码到底出了什么问题——但简单地显示所需的结果可能会让这一点变得显而易见。@Muhammad Asif Khan我将使用你的最后一句话亲爱的@JohnE,我对我的问题进行了编辑,以便你能容易地理解。请看上面的编辑!亲爱的@ JohnE,请考虑上面的最后一个编辑。给出了具有期望输出的数据。输入和输出都是数据帧。如你所见,我只是计算每个接收器(R1和R2)的重试==1和类型==“数据”的行数。我的答案是正确的,但我给你奖金是因为我必须给别人。此外,pivot_桌的触感很好。哈哈,很有道理。如果这个问题和以前一样,那就容易了。我现在看到了更新:)谢谢大家,并对之前给大家带来的不便表示歉意!