在数据框中使用数组对列进行排序

时间:2018-05-18 14:51:59

标签: python arrays pandas sorting dataframe

我正在寻找一种通过由数组组成的列对数据帧进行排序的方法。下面是我的数据框,包含索引,数组(a)和值(b)。

index    a   b
0       [0]  0.014066
1       [1]  0.569054
2       [2]  0.379795
3       [3]  0.037084
4       [4]  0.699488
5       [5]  0.191816
6       [6]  0.107417
7    [0, 4]  0.008951
8    [0, 5]  0.002558
9    [0, 6]  0.002558
10   [1, 4]  0.448849
11   [1, 5]  0.089514
12   [1, 6]  0.030691
13   [2, 4]  0.217391
14   [2, 5]  0.095908
15   [2, 6]  0.066496
16   [3, 4]  0.024297
17   [3, 5]  0.003836
18   [3, 6]  0.007673
19   [0, 3]  0.000000
20   [1, 3]  0.000000
21   [2, 3]  0.000000

如前所见,最后3个数组的排序方式与其他数组不同。我想要的是:

index    a   b
0       [0]  0.014066
1       [1]  0.569054
2       [2]  0.379795
3       [3]  0.037084
4       [4]  0.699488
5       [5]  0.191816
6       [6]  0.107417
-> [0,3] here
7    [0, 4]  0.008951
8    [0, 5]  0.002558
9    [0, 6]  0.002558
-> [1,3] here
10   [1, 4]  0.448849
11   [1, 5]  0.089514
12   [1, 6]  0.030691
-> [2,3] here
13   [2, 4]  0.217391
14   [2, 5]  0.095908
15   [2, 6]  0.066496
16   [3, 4]  0.024297
17   [3, 5]  0.003836
18   [3, 6]  0.007673

希望这是有道理的。提前致谢! df.sort_values('a')似乎不起作用。仅限于b。

中的值

3 个答案:

答案 0 :(得分:3)

来自jpp的数据

from natsort import natsorted
natsorted(s)
Out[940]: [[0], [0, 3], [0, 4], [1], [2], [3, 6]]

更新

s.iloc[natsorted(range(len(s)), key=lambda k: (len(s[k]),s[k]))]
Out[997]: 
0       [0]
1       [1]
2       [2]
5    [0, 3]
3    [0, 4]
4    [3, 6]
dtype: object

答案 1 :(得分:2)

感谢@jpp让我直接使用len

locsortedkey参数

一起使用
m = {k: (len(v), tuple(v)) for k, v in df.a.items()}
df.loc[sorted(df.index, key=m.get)]

            a         b
index                  
0         [0]  0.014066
1         [1]  0.569054
2         [2]  0.379795
3         [3]  0.037084
4         [4]  0.699488
5         [5]  0.191816
6         [6]  0.107417
19     [0, 3]  0.000000
7      [0, 4]  0.008951
8      [0, 5]  0.002558
9      [0, 6]  0.002558
20     [1, 3]  0.000000
10     [1, 4]  0.448849
11     [1, 5]  0.089514
12     [1, 6]  0.030691
21     [2, 3]  0.000000
13     [2, 4]  0.217391
14     [2, 5]  0.095908
15     [2, 6]  0.066496
16     [3, 4]  0.024297
17     [3, 5]  0.003836
18     [3, 6]  0.007673

旧答案

df.loc[sorted(df.index, key=lambda i: (lambda t: (len(t), tuple(t)))(df.at[i, 'a']))]

            a         b
index                  
0         [0]  0.014066
1         [1]  0.569054
2         [2]  0.379795
3         [3]  0.037084
4         [4]  0.699488
5         [5]  0.191816
6         [6]  0.107417
19     [0, 3]  0.000000
7      [0, 4]  0.008951
8      [0, 5]  0.002558
9      [0, 6]  0.002558
20     [1, 3]  0.000000
10     [1, 4]  0.448849
11     [1, 5]  0.089514
12     [1, 6]  0.030691
21     [2, 3]  0.000000
13     [2, 4]  0.217391
14     [2, 5]  0.095908
15     [2, 6]  0.066496
16     [3, 4]  0.024297
17     [3, 5]  0.003836
18     [3, 6]  0.007673

答案 2 :(得分:2)

看起来你需要按列表长度排序,然后按列表本身排序。

您可以使用numpy.lexsort执行此操作。这是一个最小的例子。

import numpy as np

s = pd.Series([[0], [1], [2], [0, 4], [3, 6], [0, 3]])

res = np.lexsort((s, s.str.len()))

# array([0, 1, 2, 5, 3, 4], dtype=int64)

因此,您可以使用数据框执行此操作:

df = df.iloc[np.lexsort((df['a'], df['a'].str.len()))]

请注意,np.lexsort语法从右到左工作,即排序首先按照上述逻辑执行。