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_桌的触感很好。哈哈,很有道理。如果这个问题和以前一样,那就容易了。我现在看到了更新:)谢谢大家,并对之前给大家带来的不便表示歉意!