#python #pandas
#python #панды
Вопрос:
Я хочу выбрать из идентификатора столбца те уникальные элементы, которые завершены. Каждый идентификатор представляет задачу и может появляться несколько раз. Задача завершается только тогда, когда столбец состояния имеет значение 100 для каждой строки. Пример набора данных:
import pandas as pd
df = pd.DataFrame(data= {'ID': ['A', 'A', 'B', 'B', 'C', 'D'], 'Status': [100, 100, 100, 25, 100, 34]})
Ожидаемый результат:
ID Status
0 A 100
4 C 100
- A: появляется дважды с 100. A завершено
- B: появляется дважды, кроме одного с 25. B не завершено
- C: появляется один раз со 100. C завершен
- D: появляется один раз с 34. D не завершен.
Это моя работа до сих пор:
df_completed = df[df['Status']==100].drop_duplicates()
df_filtered = df[df.ID.isin(df_completed.ID) amp; (df.Status<100)]
df_completed = df_completed[~df_completed.ID.isin(df_filtered.ID)]
Как вы можете видеть, я могу получить правильный результат, но мне интересно, есть ли менее сложный способ сделать это. Кроме того, код должен быть общим, а df огромен, поэтому простота и эффективность приветствуются.
Комментарии:
1.
ID
кажется запутанным именем для поля, которое не является уникальным…
Ответ №1:
Это кажется хорошим вариантом использования для groupby
. Вот несколько примеров:
df.groupby("ID").apply(lambda df: (df.Status == 100).all())
Это дает логический статус для каждого идентификатора:
ID
A True
B False
C True
D False
Другой вариант, если на среднее значение можно положиться:
df.groupby("ID").mean().pipe(lambda df: df[df.Status == 100])
Это дает результат:
ID Status
A 100.0
C 100.0
Ответ №2:
Учитывая, что переменная является статусом, я предполагаю, что она существует исключительно [0,100]? Если это так, минимальный статус должен быть 100 для этого идентификатора.
import pandas as pd
df = pd.DataFrame(data= {'ID': ['A', 'A', 'B', 'B', 'C', 'D'], 'Status': [100, 100, 100, 25, 100, 34]})
df_completed=df.groupby(['ID']).min()==100 #gives True/False for each ID.
df_completed=df_completed[df == True].dropna()*100 #essentially just formatting
Вывод:
Status
ID
A 100.0
C 100.0
Ответ №3:
Много способов сделать это.
Вариант 1
groupby()
и отфильтруйте min==100
df.groupby('ID')['Status'].min()[lambda x:x==100].reset_index()
ID Status
0 A 100
1 C 100
Вариант 2
Фильтруйте IDs
, которые имеют какие Status
-либо значения, не равные 100
и извлекайте их index
с помощью groupby()
, filter(boolean selection)
Исключить выбранный индекс с помощью обратного .isin
запроса и drop duplicates
из результата
s=df.loc[df.groupby('ID')['Status'].filter(lambda x:(x!=100).any()).index,:]
df[~df.index.isin(s.index)].drop_duplicates()
ID Status
0 A 100
4 C 100