У меня есть большой 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]})
Обновление, ответы на вопросы:
@mozway: я улучшил описание выше в соответствии с вашими вопросами.
спасибо за обновление, если у вас есть флаг, это легко, см. ниже ;)






Вы можете использовать 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
Если у вас есть флаг для последнего элемента в блоке, вы можете использовать обратную 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
График автокорреляции:
Знаете ли вы эту последовательность заранее? Его длина? Если нет, то всегда ли оно завершено? Пожалуйста, дайте некоторый контекст, поскольку в настоящее время трудно понять, как это обобщает.