#python #pandas
Вопрос:
У меня есть этот набор данных, в котором есть имена и количество:
df = pd.DataFrame({'Id':[1,2,3,4,5,6], 'Name':['Eve','Diana','Diana','Mia','Eve','Eve'], "Count":[10,3,14,8,5,2]})
df
Id Name Count
0 1 Eve 10
1 2 Diana 3
2 3 Diana 14
3 4 Mia 8
4 5 Eve 5
5 6 Eve 2
И я хочу создать новый столбец, который представляет собой объединение имени и рейтинга. Поэтому сначала я должен выбрать эти неуникальные значения и упорядочить их:
df_nounique = df[df.duplicated(subset=['Name'], keep=False)]
df_nounique = df_nounique.sort_values(by=['Name','Count'], ascending=False)
df_nounique
Id Name Count
0 1 Eve 10
4 5 Eve 5
5 6 Eve 2
2 3 Diana 14
1 2 Diana 3
Хорошо, теперь я должен назначить рейтинг на основе имени и количества:
df_nounique['rank'] = df_nounique.groupby('Name')['Count'].rank()
df_nounique
Id Name Count rank
0 1 Eve 10 3.0
4 5 Eve 5 2.0
5 6 Eve 2 1.0
2 3 Diana 14 2.0
1 2 Diana 3 1.0
Но вот тут я и застрял. Для первой строки ранг должен быть 1, но я получаю 3!. Если я все правильно понял, я могу объединить конкатенацию, чтобы получить это:
Id Name Count New_col
0 1 Eve 10 Eve_1
1 2 Diana 3 Diana_2
2 3 Diana 14 Diana_1
3 4 Mia 8 Mia
4 5 Eve 5 Eve_2
5 6 Eve 2 Eve_3
Кажется, я предпринимаю слишком много шагов, поэтому, пожалуйста, не могли бы вы помочь мне, по крайней мере, с моей проблемой ранга и предложением лучшего подхода к моей конечной цели?
Ответ №1:
Использовать ascending=False
в качестве аргумента rank()
:
df_nounique['rank'] = df_nounique.groupby('Name')['Count']
.rank(ascending=False).astype(int)
>>> df_nounique
Id Name Count rank
0 1 Eve 10 1
4 5 Eve 5 2
5 6 Eve 2 3
2 3 Diana 14 1
1 2 Diana 3 2
Затем:
df['New_col'] = (df_nounique['Name'] '_' df_nounique['rank'].astype(str))
.combine_first(df['Name'])
>>> df
Id Name Count New_col
0 1 Eve 10 Eve_1
1 2 Diana 3 Diana_2
2 3 Diana 14 Diana_1
3 4 Mia 8 Mia
4 5 Eve 5 Eve_2
5 6 Eve 2 Eve_3
Ответ №2:
Мы также можем создавать серию напрямую, df
без необходимости df_nounique
:
- Генерация серии из
groupby rank
(сascending=False
иmethod='dense'
для обеспечения целого числа шагов) - Использование
fillna
для заполнения пропущенных значенийName
join
вернемся к кадру данных. (Series.rename
необходимо назначить новое имя столбца, так какjoin
работает только с именованными сериями):
df = df.join(
(df['Name'] '_' df[df.duplicated(subset=['Name'], keep=False)]
.groupby('Name')['Count']
.rank(ascending=False, method='dense')
.map('{:.0f}'.format)).fillna(df['Name']).rename('New_col')
)
df
:
Id Name Count New_col
0 1 Eve 10 Eve_1
1 2 Diana 3 Diana_2
2 3 Diana 14 Diana_1
3 4 Mia 8 Mia
4 5 Eve 5 Eve_2
5 6 Eve 2 Eve_3
Комментарии:
1. Я вижу, что могу избежать всего моего загроможденного кода с вашим ответом @Генри Экер, какое замечательное объяснение! Большое вам спасибо, хорошего начала недели!
Ответ №3:
хотя ответ уже выбран, этот код , я думаю, неплох… взгляните
# module
import pandas as pd
import numpy as np
# make a dataset
df = pd.DataFrame({'Id':[1,2,3,4,5,6], 'Name':['Eve','Diana','Diana','Mia','Eve','Eve'], "Count":[10,3,14,8,5,2]})
print(df)
# rank and make new column
df['rank']=df.groupby('Name')['Count'].rank(ascending=False).astype('str') #rank
df.loc[~(df.duplicated(subset=['Name'], keep=False)),'rank']=np.nan # replace rank null if value of name column is unique
df.loc[~(df['rank'].isna()),'New_col'], df.loc[(df['rank'].isna()),'New_col'] = (df['Name'] '_' df['rank']),(df['Name'])
print(df)
Комментарии:
1. Здравствуйте @Sanzo, спасибо за ответ, вы знаете, когда я запустил ваш код
Mia
, в новой колонке появляется НаН, но я просто хочу, чтобы появилось имя, если нет ранга. В любом случае, я ценю ваши усилия, я учусь на них и тоже помогаю другим2. хорошо, я могу отредактировать его, но я сделаю это позже 🙂
3. @Alexis Я отражаю твою просьбу в своем коде~! смотри последнюю строчку!
4. Спасибо, что уделили мне время @sanzo213! Это сработало отлично!