У меня есть фрейм данных pandas, как показано ниже.
ID,color
1, Yellow
1, Red
1, Green
2, Red
2, np.nan
3, Green
3, Red
3, Green
4, Yellow
4, Red
5, Green
5, np.nan
6, Red
7, Red
fd = pd.read_clipboard(sep=',')
Как вы можете видеть во входном фрейме данных, некоторые идентификаторы имеют несколько связанных с ними цветов.
Итак, всякий раз, когда с ними связано несколько цветов, я хотел бы выбрать только один цвет на основе приведенных ниже критериев.
['Green','Red','Yellow'] = Choose 'Green'
['Red', 'Yellow'] = Choose 'Yellow'
['Green', 'Yellow'] = Choose 'Green'
В основном, Зеленому отдается 1-е предпочтение. 2-е предпочтение принадлежит желтому цвету, а последнее предпочтение — красному цвету.
Таким образом, если идентификатор всегда имеет зеленый цвет, выберите зеленый (не заботьтесь о других цветах).
Если идентификатор всегда имеет желтый и красный цвет, выберите желтый.
Если идентификатор для всех его строк имеет только NA
, оставьте его как NA
Я пробовал ниже, но это дает мне только список цветов
fd.groupby('ID',as_index=False)['color'].aggregate(lambda x: list(x))
fd[final_color] = [if i[0] =='Green' for i in fd[col]]
Я ожидаю, что мой вывод будет таким, как показано ниже
Обновить
Один из способов решить эту проблему — реализовать пользовательскую сортировку:
sort_preference = {
'Green': 0,
'Yellow': 1,
}
(
fd
.sort_values(by=['color'], key=lambda x: x.map(sort_preference))
.groupby('ID')
.head(1)
)
Ответ @Shubham Sharma имеет версию без сортировки. Это достигается путем присвоения упорядоченных категорий.
Отсортируйте значения фрейма данных по цвету с помощью словаря предпочтений, затем отбросьте дубликаты на ID
d = {'Green': 1, 'Yellow': 2, 'Red': 3}
df.sort_values('color', key=lambda c: c.map(d)).drop_duplicates('ID')
Альтернативный подход: сначала преобразовать столбец color
в упорядоченный категориальный тип, затем сгруппировать и агрегировать, чтобы выбрать минимальное значение.
df['color'] = pd.Categorical(df['color'], ['Green', 'Yellow', 'Red'], True)
df.groupby('ID', as_index=False)['color'].agg('min')
ID color
0 1 Green
1 2 Red
2 3 Green
3 4 Yellow
4 5 Green
5 6 Red
6 7 Red
спасибо, проголосовал. Есть ли способ сделать это без сортировки? Или эта проблема всегда будет требовать сортировки? из-за своей природы? Скажем, если я хочу выбрать определенный цвет из списка (без каких-либо критериев), может просто показать мне, как это можно сделать? Вы также можете сохранить этот пример сортировки как есть.
Предположим, я хочу выбрать «зеленый» цвет на основе ID=1,3 и желтый цвет для ID=6,7. Можете показать мне, как это можно сделать?
@TheGreat В таком случае, какой будет выбор цвета для id 2, 4, 5?
Это немного другое требование (не связанное с этим вопросом). Я создам новый пост и свяжу его здесь
Вот соответствующий пост - stackoverflow.com/questions/71544776/…
случайно, вы не знаете, почему я получаю все NA
, когда делаю категорический заказ? обновил скрин выше в посте
@TheGreat Это связано с дополнительными пробелами в столбце цвета во входном фрейме данных. Используйте fd = pd.read_clipboard(sep=',', skipinitialspace=True)
во время чтения.
Без сортировки вы можете использовать idxmin
, если вы сопоставляете свой цвет с числовыми значениями:
d = {'Green': 1, 'Yellow': 2, 'Red': 3}
out = df.loc[df.assign(num=df['color'].map(d)).groupby('ID')['num'].idxmin()]
print(out)
# Output
ID color
2 1 Green
3 2 Red
5 3 Green
8 4 Yellow
10 5 Green
12 6 Red
13 7 Red
спасибо, проголосовал. есть ли способ сделать это без сортировки?