Python Pandas按连续值分组DataFrame
我有一个很大的 pandas 数据框,里面有一个时间戳列,一个数值列,一个“键”列,还有一个标志列,用来表示一个数据块的结束(其实还有其他列)。
timestamp, value, key, last_in_block
12345, 1.0, 2, False <-- start of block 1
12346, 0.5, 4, False
12347, 1.2, 1, False
12348, 2.2, 6, False
12349, 1.5, 3, False
12350, 1.2, 3, False
12351, 2.3, 3, False
12352, 0.4, 5, True
12371, 1.3, 2, False <-- start of block 2
12372, 0.9, 4, False
12373, 1.7, 1, False
12374, 2.0, 6, False
12375, 1.2, 3, False
12376, 1.4, 3, False
12377, 2.7, 3, False
12378, 0.8, 5, True
...
在“键”列中,有一串特定的数值序列(在这个例子中是 2 4 5 6 3 3 3 5),这个序列用来标识一个数据块。我想用“groupBy”语句把这个数据框按块分组。请问这怎么做?
df = pd.DataFrame(data =
{"timestamp": list(range(12345,12353)) + list(range(12371,12379)),
"value": [1.0,0.5,1.2,2.2,1.5,1.2,2.3,0.4,1.3,0.9,1.7,2.0,1.2,1.4,2.7,0.8],
"key": [2,4,1,6,3,3,3,5]*2,
"last_in_block" : [False]*7+[True]+[False]*7+[True]})
更新,关于问题的回答:
- 我事先知道这个序列
- 除了非常少见的例外,这些序列都是完整的
2 个回答
1
如果你有一个标记,表示每个区块的最后一个项目,你可以使用反向的 cumsum
来形成分组:
group = df.loc[::-1, 'last_in_block'].cumsum()
for k, g in df.groupby(group, sort=False):
print(g)
另外,如果你不知道周期性或者没有标记,你可以通过自相关来估算周期性,使用 autocorr
方法在关键数据上进行计算,周期性对应于最大相关性的滞后值:
lag = pd.Series({i: df['key'].autocorr(i)
for i in range(1, len(s)//2+1)}
).idxmax()
# periodicity: 8
group = np.arange(len(df))//lag
for k, g in df.groupby(group, sort=False):
print(g)
输出结果:
timestamp value key last_in_block
0 12345 1.0 2 False
1 12346 0.5 4 False
2 12347 1.2 1 False
3 12348 2.2 6 False
4 12349 1.5 3 False
5 12350 1.2 3 False
6 12351 2.3 3 False
7 12352 0.4 5 True
timestamp value key last_in_block
8 12371 1.3 2 False
9 12372 0.9 4 False
10 12373 1.7 1 False
11 12374 2.0 6 False
12 12375 1.2 3 False
13 12376 1.4 3 False
14 12377 2.7 3 False
15 12378 0.8 5 True
自相关图:
1
你可以用 last_in_block
来识别不同的组,然后再用 groupby
来分组:
df["last_in_block"] = np.where(df["last_in_block"].shift(), 1, 0)
df["last_in_block"] = df["last_in_block"].cumsum()
grouped = df.groupby("last_in_block")
grouped.groups
:
{1: [0, 1, 2, 3, 4, 5, 6, 7], 2: [8, 9, 10, 11, 12, 13, 14, 15]}
grouped.mean()
:
timestamp value key
last_in_block
1 12348.5 1.2875 3.375
2 12374.5 1.5000 3.375