在Pandas中按升序和降序有条件地对单个列进行排序

时间:2018-06-20 21:56:51

标签: python python-3.x pandas sorting pandas-groupby

我有98,000个美国家庭街道地址,我需要按照“步行”顺序进行排序,即按照您步行的顺序列出,沿着街道的一侧,然后过马路然后向后走。

import pandas as pd
df = pd.read_excel('c:pdsort.xlsx')

# add boolean column for even or odd on number column
is_even = df.loc[:,'number'] % 2 == 0
df.loc[:, 'even'] = is_even

# group and then sort by number
df.groupby(['town','street','even']).apply(lambda x: x.sort_values('number'))

# sort odd numbers ascending and even numbers descending

所需的df结果,对奇数的街道编号进行升序排序,然后切换为偶数的降序排序。 [抱歉,第一个stackoverflow问题,尚不具备复制Jupyter笔记本图像的条件]

4列:数字,街道,城镇,偶数

'number'列的期望结果: 1231 1233 1235 1237 1239 1238 1236 1234 1232 1230

2 个答案:

答案 0 :(得分:1)

使用numpy.lexsort,您可以定义要排序的序列序列。来自@smj的数据。

设置

import pandas as pd
import numpy as np

number_list = list(range(1, 11))

df = pd.DataFrame({'town': sorted(['Springfield', 'Shelbyville'] * 10),
                   'street': sorted(['Evergreen Terrace', 'Main Street'] * 10),
                   'number': number_list + number_list})

解决方案

在订购时要小心。 np.lexsort从序列的最后一个元素开始工作;例如s1的排序优先级最高,s4的排序优先级最低。

s1 = df['town']
s2 = df['street']
s3 = ~df['number']%2                            # i.e. "is odd"
s4 = np.where(s3, -df['number'], df['number'])  # i.e. "negate if odd"

res = df.iloc[np.lexsort((s4, s3, s2, s1))]

结果

print(res)

           town             street  number
0   Shelbyville  Evergreen Terrace       1
2   Shelbyville  Evergreen Terrace       3
4   Shelbyville  Evergreen Terrace       5
6   Shelbyville  Evergreen Terrace       7
8   Shelbyville  Evergreen Terrace       9
9   Shelbyville  Evergreen Terrace      10
7   Shelbyville  Evergreen Terrace       8
5   Shelbyville  Evergreen Terrace       6
3   Shelbyville  Evergreen Terrace       4
1   Shelbyville  Evergreen Terrace       2
10  Springfield        Main Street       1
12  Springfield        Main Street       3
14  Springfield        Main Street       5
16  Springfield        Main Street       7
18  Springfield        Main Street       9
19  Springfield        Main Street      10
17  Springfield        Main Street       8
15  Springfield        Main Street       6
13  Springfield        Main Street       4
11  Springfield        Main Street       2

答案 1 :(得分:0)

如果我对您的理解正确,这是我的尝试,我敢肯定这可以通过lambda函数完成,但它有助于以冗长的方式阐明逻辑:)

import pandas as pd
import numpy as np

number_list = list(range(1, 11))

data = pd.DataFrame(
    {
        'town': sorted(['Springfield', 'Shelbyville'] * 10),
        'street': sorted(['Evergreen Terrace', 'Main Street'] * 10),
        'number': number_list + number_list
    }
)

data['is_even'] = data['number'] % 2 == 0

final = pd.DataFrame()

for key, data_group in data.groupby(['town', 'street', 'is_even']):
    if key[2] == True:
        final = final.append(data_group.sort_values('number', ascending = False))
    else:
        final = final.append(data_group.sort_values('number'))

final.drop('is_even', axis = 1, inplace = True)

final

礼物:

enter image description here