如何在Pandas中不是按行而是按列对值排序?

时间:2019-10-22 04:21:59

标签: python pandas dataframe

假设我有这个数据框。

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

例如:要到达A商店,需要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 个答案:

答案 0 :(得分:3)

想法是使用Series.str.splitDataFrame.stack重塑值,然后按第一级和time列排序,按GroupBy.cumcount创建新顺序,最后重塑为原始值:< / p>

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 :(得分:1)

这可能是更长的方法。也许有人可以给您更好的方法。但这会提供您需要的输出。

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