Создайте объединяющее имя и рейтинг на основе столбцов в панд

#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 :

  1. Генерация серии из groupby rank ascending=False и method='dense' для обеспечения целого числа шагов)
  2. Использование fillna для заполнения пропущенных значений Name
  3. 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! Это сработало отлично!