У меня есть фрейм данных, содержащий пару ACQ/REL, как показано ниже:
import pandas as pd
data = [
['2023-06-05 16:51:27.561','ACQ','location'],
['2023-06-05 16:51:27.564','ACQ','location'],
['2023-06-05 16:51:27.567','ACQ','location'],
['2023-06-05 16:51:27.571','REL','location'],
['2023-06-05 16:51:27.573','REL','location'],
['2023-06-05 16:51:27.587','REL','location'],
['2023-06-05 16:51:28.559','ACQ','location'],
['2023-06-05 16:51:28.561','ACQ','location'],
['2023-06-05 16:51:28.563','ACQ','location'],
['2023-06-05 16:51:28.566','REL','location'],
['2023-06-05 16:51:28.569','REL','location'],
['2023-06-05 16:51:28.575','REL','location']
]
df = pd.DataFrame(data,columns=['ts','action','name'])
Я бы реорганизовал его по парам ACQ/REL, внешние пары ACQ/REL как группу, чтобы выходной фрейм данных выглядел следующим образом:
0 2023-06-05 16:51:27.561 ACQ location
5 2023-06-05 16:51:27.587 REL location
1 2023-06-05 16:51:27.564 ACQ location
4 2023-06-05 16:51:27.573 REL location
2 2023-06-05 16:51:27.567 ACQ location
3 2023-06-05 16:51:27.571 REL location
6 2023-06-05 16:51:28.559 ACQ location
11 2023-06-05 16:51:28.575 REL location
7 2023-06-05 16:51:28.561 ACQ location
10 2023-06-05 16:51:28.569 REL location
8 2023-06-05 16:51:28.563 ACQ location
9 2023-06-05 16:51:28.566 REL location
Текущий пример - 3 пары в группе, но это не всегда одно и то же. Каков правильный способ получить такие результаты?






Если всегда гарантируется, что существует одинаковое количество ACQ и REL, и что они, соответственно, в правильном порядке (т. исходный список сначала на два, по второму элементу, а затем в цикле для вывода одного из каждого списка.
Код:
import pandas as pd
data = [
['2023-06-05 16:51:27.561', 'ACQ', 'location'],
['2023-06-05 16:51:27.564', 'ACQ', 'location'],
['2023-06-05 16:51:27.567', 'ACQ', 'location'],
['2023-06-05 16:51:27.571', 'REL', 'location'],
['2023-06-05 16:51:27.573', 'REL', 'location'],
['2023-06-05 16:51:27.587', 'REL', 'location'],
['2023-06-05 16:51:28.559', 'ACQ', 'location'],
['2023-06-05 16:51:28.561', 'ACQ', 'location'],
['2023-06-05 16:51:28.563', 'ACQ', 'location'],
['2023-06-05 16:51:28.566', 'REL', 'location'],
['2023-06-05 16:51:28.569', 'REL', 'location'],
['2023-06-05 16:51:28.575', 'REL', 'location']
]
df = pd.DataFrame(data, columns=['ts', 'action', 'name'])
# print(df)
data_acq = []
data_rel = []
for index, row in df.iterrows():
if row['action'] == 'ACQ':
data_acq.append(row)
elif row['action'] == 'REL':
data_rel.append(row)
assert len(data_acq) == len(data_rel)
df_new = pd.DataFrame([], columns=['ts', 'action', 'name'])
for j in range(len(data_acq)):
df_new = pd.concat([
df_new,
pd.DataFrame([
data_acq[j], data_rel[j]
])
])
print(df_new)
Выход:
ts action name
0 2023-06-05 16:51:27.561 ACQ location
3 2023-06-05 16:51:27.571 REL location
1 2023-06-05 16:51:27.564 ACQ location
4 2023-06-05 16:51:27.573 REL location
2 2023-06-05 16:51:27.567 ACQ location
5 2023-06-05 16:51:27.587 REL location
6 2023-06-05 16:51:28.559 ACQ location
9 2023-06-05 16:51:28.566 REL location
7 2023-06-05 16:51:28.561 ACQ location
10 2023-06-05 16:51:28.569 REL location
8 2023-06-05 16:51:28.563 ACQ location
11 2023-06-05 16:51:28.575 REL location
Попробуй это:
df.sort_values('ts').assign(sortkey=df.groupby('action').cumcount()).sort_values(['sortkey','action'])
Выход:
ts action name sortkey
0 2023-06-05 16:51:27.561 ACQ location 0
3 2023-06-05 16:51:27.571 REL location 0
1 2023-06-05 16:51:27.564 ACQ location 1
4 2023-06-05 16:51:27.573 REL location 1
2 2023-06-05 16:51:27.567 ACQ location 2
5 2023-06-05 16:51:27.587 REL location 2
6 2023-06-05 16:51:28.559 ACQ location 3
9 2023-06-05 16:51:28.566 REL location 3
7 2023-06-05 16:51:28.561 ACQ location 4
10 2023-06-05 16:51:28.569 REL location 4
8 2023-06-05 16:51:28.563 ACQ location 5
11 2023-06-05 16:51:28.575 REL location 5
Используя список в качестве стека, вы можете вычислить смещения для REL, которые указывают, насколько далеко назад расположен соответствующий ACQ (т. е. индекс ACQ). Затем отсортируйте индексы в соответствии с скорректированными позициями (ACQ остается в исходной позиции, а REL смещается обратно к позиции ACQ), чтобы получить индексы в новом порядке:
acq = list() # stack of ACQ positions
iREL = enumerate(x= = "REL" for _,x,_ in data) # identify REL indices
offsets = (acq.pop() if rel else acq.append(i) or i for i,rel in iREL)
order = (i for i,_ in sorted(enumerate(offsets),key=lambda x:x[::-1]))
data = [data[i] for i in order] # reorder data : df.reindex(order)
print(*data,sep = "\n")
['2023-06-05 16:51:27.561', 'ACQ', 'location']
['2023-06-05 16:51:27.587', 'REL', 'location']
['2023-06-05 16:51:27.564', 'ACQ', 'location']
['2023-06-05 16:51:27.573', 'REL', 'location']
['2023-06-05 16:51:27.567', 'ACQ', 'location']
['2023-06-05 16:51:27.571', 'REL', 'location']
['2023-06-05 16:51:28.559', 'ACQ', 'location']
['2023-06-05 16:51:28.575', 'REL', 'location']
['2023-06-05 16:51:28.561', 'ACQ', 'location']
['2023-06-05 16:51:28.569', 'REL', 'location']
['2023-06-05 16:51:28.563', 'ACQ', 'location']
['2023-06-05 16:51:28.566', 'REL', 'location']
Если данные уже находятся в фрейме данных, список order можно использовать для сортировки фрейма данных с помощью метода reindex().