Упорядочение по столбцам в кадре данных на основе пользовательского списка - PullRequest
4 голосов
/ 21 марта 2019

Я вижу решения для сортировки записей по вертикали, однако я хочу расположить подмножество моих данных в моем фрейме данных по горизонтали.

Вот мой фрейм данных с данными, которые я хочу отсортировать:

account_num Word_0    Word_1    Word_2    Word_3    Word_4
123         Silver    Platinum  Osmium    
456         Platinum  
789         Silver    Rhodium   Platinum  Osmium    

и вот мой желаемый результат:

account_num  Word_0     Word_1    Word_2   Word_3   Word_4
123          Platinum   Osmium    Silver   
456          Platinum   
789          Rhodium    Platinum  Osmium   Silver   

На основе порядка в этом кадре данных:

Priority    Metal
1           Rhodium
2           Platinum
3           Gold
4           Ruthenium
5           Iridium
6           Osmium
7           Palladium
8           Rhenium
9           Silver
10          Indium

Мне уже удалось привести в порядок данные, используя этот фрагмент кода:

newdf.apply(lambda r: sorted(r,reverse = True), axis = 1)

, где столбцы с Word_0 по 4 помещаются в другой фрейм данных (newdf), а затем сортируются в обратном порядке, так что пустые значения появляются последними, и затем они присоединяются к моему исходному фрейму данных, содержащему столбец account_num, однако у меня естьне знаю, как включить пользовательский список в последовательность заказа.

Любая помощь будет принята с благодарностью

Спасибо

Ответы [ 4 ]

3 голосов
/ 21 марта 2019

Вы также можете попробовать:

df=df.fillna(value=pd.np.nan)
d=dict(zip(ref.Metal,ref.Priority))
df[['account_num']].join(pd.DataFrame(np.sort(df.iloc[:,1:].replace(d).values,axis=1),
                        columns=df.iloc[:,1:].columns).replace({v:k for k,v in d.items()}))

   account_num    Word_0    Word_1  Word_2  Word_3 Word_4
0          123  Platinum    Osmium  Silver     NaN    NaN
1          456  Platinum       NaN     NaN     NaN    NaN
2          789   Rhodium  Platinum  Osmium  Silver    NaN
3 голосов
/ 21 марта 2019

Использование pd.Categorical

c = pd.Categorical(df2.Metal, df2.Metal, ordered=True)

df.set_index('account_num').transform(lambda k: pd.Categorical(k, 
                                                           categories=c.categories)\
                                  .sort_values(), axis=1)

Выходы

            Word_0       Word_1     Word_2  Word_3  Word_4
account_num                 
123         Platinum     Osmium     Silver  NaN     NaN
456         Platinum     NaN        NaN     NaN     NaN
789         Rhodium      Platinum   Osmium  Silver  NaN

Конечно, всегда можно .fillna('') в конце.

3 голосов
/ 21 марта 2019

Я чувствую, что мы можем melt это, merge заказ df, затем sort_values основание на Priority и pivot это обратно

s=df.melt('account_num').\
     merge(orderdf,left_on='value',right_on='Metal',how='left').\
       sort_values('Priority')
yourdf=s.assign(newkey=s.groupby('account_num').cumcount()).\
           pivot('account_num','newkey','value').add_prefix('Word_')
yourdf
Out[1100]: 
newkey         Word_0    Word_1  Word_2  Word_3 Word_4
account_num                                           
123          Platinum    Osmium  Silver    None    NaN
456          Platinum      None    None    None    NaN
789           Rhodium  Platinum  Osmium  Silver    NaN

Или мы используем более ясную логику с argsort

d = dict(zip(df2['Metal'], df2['Priority']))
for x in range(len(df)):

    df.iloc[x,:]=df.values[x,np.argsort([d.get(x) if x ==x else 1000 for x in df.values[x,:]] )]

df
Out[38]: 
                 Word_0    Word_1  Word_2  Word_3  Word_4
  account_num                                            
0 123          Platinum    Osmium  Silver     NaN     NaN
1 456          Platinum       NaN     NaN     NaN     NaN
2 789           Rhodium  Platinum  Osmium  Silver     NaN
2 голосов
/ 21 марта 2019

Использование:

#create helper dictionary
d = dict(zip(df2['Metal'], df2['Priority']))
#add empty string for maximum priority
d[''] = df2['Priority'].max() + 1

#use sorted by key and dictioanry
L = [sorted(x, key=d.get) for x in df.fillna('').values]
#create new DataFrame by constructor
df1 = pd.DataFrame(L, index=df.index).add_prefix('Word_')
print (df1)
               Word_0    Word_1  Word_2  Word_3 Word_4
account_num                                           
123          Platinum    Osmium  Silver               
456          Platinum                                 
789           Rhodium  Platinum  Osmium  Silver     

При необходимости пропустить значения:

df1 = pd.DataFrame(L, index=df.index).add_prefix('Word_').replace('', np.nan)
print (df1)
               Word_0    Word_1  Word_2  Word_3  Word_4
account_num                                            
123          Platinum    Osmium  Silver     NaN     NaN
456          Platinum       NaN     NaN     NaN     NaN
789           Rhodium  Platinum  Osmium  Silver     NaN  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...