考虑数据帧"数据"由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
答案 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
事实上,resample
和groupby
+ 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
快速讨论不同方法:在许多情况下,unstack
和pivot_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