Как отсортировать значения не по строкам, а по столбцам в Pandas? - PullRequest
3 голосов
/ 22 октября 2019

Допустим, у меня есть этот фрейм данных.

df = pd.DataFrame([['A-store',5,'B-store',4,'C-store',6], \
                   ['B-store',3,'P-store',4,np.nan,np.nan], \
                   ['N-store',20,np.nan,np.nan,'I-store',9], \
                   ['L-store',8,'N-store',2,'A-store',5]],
           columns=['store_1','time_1','store_2','time_2','store_3','time_3'])
   store_1  time_1  store_2  time_2  store_3  time_3
0  A-store       5  B-store     4.0  C-store     6.0
1  B-store       3  P-store     4.0      NaN     NaN
2  N-store      20      NaN     NaN  I-store     9.0
3  L-store       8  N-store     2.0  A-store     5.0

Пример: чтобы попасть в А-магазин, требуется 5 минут.

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

Вот идеальный вывод.

shorter <----------------------------------->  longer
   store_1  time_1  store_2  time_2  store_3  time_3
0  B-store     4.0  A-store       5  C-store     6.0
1  B-store       3  P-store     4.0      NaN     NaN
2  I-store     9.0  N-store      20      NaN     NaN
3  N-store     2.0  A-store     5.0  L-store       8

Возможно, я мог бы поворачиваться или складываться, и сортировать по строкам. Но я не уверен, как это сделать.

Если у кого-нибудь есть какие-нибудь хорошие идеи или коды, дайте мне знать.

Спасибо!

Ответы [ 2 ]

3 голосов
/ 22 октября 2019

Идея заключается в изменении значений с Series.str.split и DataFrame.stack, затем сортировка по первому уровню и столбцу time, создание нового заказа по GroupBy.cumcount и последнее изменение в исходном виде:

df.columns = df.columns.str.split('_', expand=True)

df1=df.stack().reset_index(level=1,drop=True).rename_axis('lvl1').sort_values(['lvl1','time'])
df1 = df1.set_index(df1.groupby(level=0).cumcount().add(1), append=True)

df1 = df1.unstack().sort_index(axis=1, level=1).rename_axis(None)
df1.columns = [f'{a}_{b}' for a, b in df1.columns]
print (df1)
   store_1  time_1  store_2  time_2  store_3  time_3
0  B-store     4.0  A-store     5.0  C-store     6.0
1  B-store     3.0  P-store     4.0      NaN     NaN
2  I-store     9.0  N-store    20.0      NaN     NaN
3  N-store     2.0  A-store     5.0  L-store     8.0
1 голос
/ 22 октября 2019

Это может быть более длинный способ сделать это. Может быть, кто-то может дать вам лучший подход. Но это дает нужный вам вывод.

import pandas as pd
import numpy as np
import operator

def func(lst):
    d = ({lst[i]: lst[i + 1] for i in range(0, len(lst), 2)})
    d = sorted(d.items(), key=operator.itemgetter(1))
    return [val for sublist in d for val in sublist]

df = pd.DataFrame([['A-store',5,'B-store',4,'C-store',6], \
                   ['B-store',3,'P-store',4,np.nan,np.nan], \
                   ['N-store',20,np.nan,np.nan,'I-store',9], \
                   ['L-store',8,'N-store',2,'A-store',5]],
           columns=['store_1','time_1','store_2','time_2','store_3','time_3'])

pd.DataFrame.from_records(df.apply(lambda x : func(x),axis=1) columns=['store_1','time_1','store_2','time_2','store_3','time_3'],

)

Это вернет нижеследующее как вывод.

    store_1 time_1  store_2 time_2  store_3 time_3
0   B-store 4.0     A-store 5.0     C-store 6.0
1   B-store 3.0     P-store 4.0     NaN     NaN
2   N-store 20.0    NaN     NaN     I-store 9.0
3   N-store 2.0     A-store 5.0     L-store 8.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...