【问题标题】:Conditionally sort a single column in ascending and descending order in Pandas在 Pandas 中有条件地按升序和降序对单个列进行排序
【发布时间】:2018-11-30 03:26:17
【问题描述】:

我有 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 列:数字、街道、城镇、偶数

列“数字”的期望结果: 1231 1233 1235 1237 1239 1238 1236 1234 1232 1230

【问题讨论】:

  • 如果我理解正确的话,你首先要groupby street。 然后您对奇数/偶数进行分区,对每个列表进行排序,并根据需要连接结果。作为最终输出,您是否将整个数据库按新顺序排序?请给出一个样本输入和期望的输出,其中包含两到三条街道,每条街道可能有四栋房屋。

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


【解决方案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

【讨论】:

  • 试过 smj 和 jpp 都回答了我的问题,不能 pandasice piRSquared,在 Jupyter NB 上运行 %%timeit - 选项 smj 16.7 s ± 227 ms 每个循环(平均值 ± 标准开发。 7 次运行,每次 1 个循环)选项 jpp 1.24 s ± 2.6 ms 每个循环(平均值±标准偏差。7 次运行,每个循环 1 个)-非常感谢,所有 98k 地址都已排序!
  • 好答案,我不得不离开中间答案(-:
【解决方案2】:

如果我理解正确,这是我的尝试,我确信这可以在 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

给予:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-18
    • 2020-11-09
    • 2020-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多