我有一个熊猫multiIndex数据框,我想按名称和编号进行排序。
以类似的数据集df为例创建:
random= np.random.rand(3,10)
a = [ 'a','b','a','b','a','b','a','b','a', 'b']
b = ['p11_1','p11_1','p1_1','p1_1','p9_1','p9_1','p10_1','p10_1','p1_2','p1_2']
arrays = [a,b]
df = pd.DataFrame(data = random, columns = arrays)
标题层如下:
a b a ... b a b
p11_1 p11_1 p1_1 ... p10_1 p1_2 p1_2
我可以使用简单的sort命令,但是会导致错误的输出:
df = df.sort_index(axis=1)
标题层如下:
a ... b
p10_1 p11_1 p1_1 ... p1_1 p1_2 p9_1
这对两层都进行排序,但是第二层不是所需的输出。
所需的输出按如下顺序排列第二层:
p1_1 < p1_2 < p9_1 < p10_1 < p11_1
而不是:
p10_1 < p11_1 < p1_1 < p1_2 < p9_1
有什么用!
答案 0 :(得分:2)
您可以使用正则表达式提取数字,转换为int
并排序:
import re
new_cols = sorted(df.columns, key=lambda x: (x[0],)+tuple(map(int, re.findall('(\d+)', x[1])) ))
df = df[new_cols]
输出:
a b \
p1_1 p1_2 p9_1 p10_1 p11_1 p1_1 p1_2
0 0.573945 0.648582 0.018916 0.349072 0.242901 0.672357 0.264832
1 0.362348 0.046961 0.245218 0.971988 0.337589 0.868794 0.357096
2 0.653817 0.882649 0.103931 0.778984 0.777559 0.056299 0.252898
p9_1 p10_1 p11_1
0 0.645881 0.633993 0.340431
1 0.908928 0.527769 0.862013
2 0.302780 0.497609 0.378155
答案 1 :(得分:2)
考虑到您需要自然排序第二级,可以致电numpy.lexsort
:
get_level = df.columns.get_level_values
idx = np.lexsort((
get_level(1).str.extract(f'p(\d+)', expand=False).astype(int), get_level(0)))
df.iloc[:, idx]
a ... b
p1_1 p1_2 p9_1 ... p9_1 p10_1 p11_1
0 0.879848 0.384629 0.006705 ... 0.296052 0.716751 0.790975
1 0.139579 0.158237 0.737015 ... 0.702624 0.356452 0.557185
2 0.335480 0.133805 0.040322 ... 0.161040 0.622088 0.219986
答案 2 :(得分:2)
让我们尝试Stackoverflow
natsorted