#python #pandas
#python #pandas
Вопрос:
У меня есть df, который содержит различные элементы. Использование ниже ID
должно содержать элементы из последующих списков в любом порядке. Таким образом, либо A
или B
должно предшествовать X
или Y
, а затем следовать либо C
или D
.
Чего я надеюсь достичь, так это когда X или Y не предшествует A
или B
или за которым следует C
или D
, затем уведомить с помощью оператора и полностью удалить оскорбительные строки.
import pandas as pd
df = pd.DataFrame({
'Time' : [1,1,1,2,2,2,3,3,4,4,4,5,5],
'ID' : ['A','Y','C','B','X','D','B','X','A','Y','D','Y','D'],
})
items_before = ['A','B']
items_after = ['C','D']
specific_items = ['X','Y']
# Notify when no preceding item
for line in df[(df['ID'].isin(specific_items) amp; df['ID'].shift(1).isin(specific_items))].iterrows():
print(f'No item found for: Time {line[1].Time}')
# Notify when no subsequent item
for line in df[(df['ID'].isin(specific_items) amp; df['ID'].shift(-1).isin(specific_items))].iterrows():
print(f'No item found for: Time {line[1].Time}')
Текущий вывод:
Time ID
0 1 A
1 1 Y
2 1 C
3 2 B
4 2 X
5 2 D
6 3 B
7 3 X
8 4 A # C or D is missing here
9 4 Y
10 4 D
11 5 Y # A or B is missing here
12 5 D
Предполагаемый результат:
No subsequent item found for: Time 4
No previous item found for: Time 5
Time ID
0 1 A
1 1 Y
2 1 C
3 2 B
4 2 X
5 2 D
6 4 A
7 4 Y
8 4 D
Ответ №1:
Вам нужно протестировать все три маски вместе на наличие последовательных значений:
#if necessary first filter only matched rows by all joined values
df = df[df['ID'].isin(items_before items_after specific_items)]
m1 = df['ID'].isin(items_before) amp; df['ID'].shift(-1).isin(specific_items) amp; df['ID'].shift(-2).isin(items_after)
m2 = df['ID'].shift().isin(items_before) amp; df['ID'].isin(specific_items) amp; df['ID'].shift(-1).isin(items_after)
m3 = df['ID'].shift(2).isin(items_before) amp; df['ID'].shift().isin(specific_items) amp; df['ID'].isin(items_after)
mask = (m1| m2 | m3)
df1 = df[mask]
print (df1)
Time ID
0 1 A
1 1 Y
2 1 C
3 2 B
4 2 X
5 2 D
8 4 A
9 4 Y
10 4 D
Затем анализируются не совпадающие строки для предыдущих и последующих Time
:
df2 = df[~mask]
print (df2)
Time ID
6 3 B
7 3 X
11 5 Y
12 5 D
m11 = df2['ID'].isin(items_before) amp; df2['ID'].shift(-1).isin(specific_items)
m12 = df2['ID'].isin(specific_items) amp; df2['ID'].shift().isin(items_before)
m21 = df2['ID'].isin(specific_items) amp; df2['ID'].shift(-1).isin(items_after)
m22 = df2['ID'].isin(items_after) amp; df2['ID'].shift().isin(specific_items)
# Notify when no preceding item
for t in df2.loc[m11| m12, 'Time'].unique():
print(f'No subsequent item found for: Time {t}')
for t in df2.loc[m21| m22, 'Time'].unique():
print(f'No previous item found for: Time {t}')
No subsequent item found for: Time 3
No previous item found for: Time 5
Если требуется решение для тестирования по группам с помощью Time
:
df = df[df['ID'].isin(items_before items_after specific_items)]
m1 = df['ID'].isin(items_before) amp; df.groupby('Time')['ID'].shift(-1).isin(specific_items) amp; df.groupby('Time')['ID'].shift(-2).isin(items_after)
m2 = df.groupby('Time')['ID'].shift().isin(items_before) amp; df['ID'].isin(specific_items) amp; df.groupby('Time')['ID'].shift(-1).isin(items_after)
m3 = df.groupby('Time').shift(2)['ID'].isin(items_before) amp; df.groupby('Time')['ID'].shift().isin(specific_items) amp; df['ID'].isin(items_after)
mask = (m1| m2 | m3)
df1 = df[mask]
print (df1)
df2 = df[~mask]
print (df2)
m11 = df2['ID'].isin(items_before) amp; df2.groupby('Time')['ID'].shift(-1).isin(specific_items)
m12 = df2['ID'].isin(specific_items) amp; df2.groupby('Time')['ID'].shift().isin(items_before)
m21 = df2['ID'].isin(specific_items) amp; df2.groupby('Time')['ID'].shift(-1).isin(items_after)
m22 = df2['ID'].isin(items_after) amp; df2.groupby('Time')['ID'].shift().isin(specific_items)
# Notify when no preceding item
for t in df2.loc[m11| m12, 'Time'].unique():
print(f'No subsequent item found for: Time {t}')
for t in df2.loc[m21| m22, 'Time'].unique():
print(f'No previous item found for: Time {t}')
Комментарии:
1. Ты такой хвастун со всеми своими классными трюками :). Просто шучу. никогда не думал об использовании или для получения истинного утверждения. Классная штука. Спасибо, Джо
2. Не забудьте также фактически удалить оскорбительные строки 😉