首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >pandas中的Groupwise排序

pandas中的Groupwise排序
EN

Stack Overflow用户
提问于 2018-04-23 00:39:23
回答 2查看 1K关注 0票数 6

我想对另一个数组中定义的组边界内的数组进行排序。组不会以任何方式预先排序,并且在排序后需要保持不变。在numpy术语中,它看起来如下所示:

代码语言:javascript
复制
import numpy as np

def groupwise_sort(group_idx, a, reverse=False):
    sortidx = np.lexsort((-a if reverse else a, group_idx))
    # Reverse sorting back to into grouped order, but preserving groupwise sorting
    revidx = np.argsort(np.argsort(group_idx, kind='mergesort'), kind='mergesort')
    return a[sortidx][revidx]

group_idx =   np.array([3, 2, 3, 2, 2, 1, 2, 1, 1])
a =           np.array([3, 2, 1, 7, 4, 5, 5, 9, 1])
groupwise_sort(group_idx, a)
# >>>            array([1, 2, 3, 4, 5, 1, 7, 5, 9])
groupwise_sort(group_idx, a, reverse=True)
# >>>            array([3, 7, 1, 5, 4, 9, 2, 5, 1])

我怎样才能用pandas做同样的事情?我看到了df.groupby()df.sort_values(),尽管我找不到一种直接的方法来实现同样的排序。如果可能的话,还有一个快速的。

EN

回答 2

Stack Overflow用户

发布于 2018-04-23 01:00:27

让我们首先做好准备:

代码语言:javascript
复制
import pandas as pd
import numpy as np

group_idx =   np.array([3, 2, 3, 2, 2, 1, 2, 1, 1])
a =           np.array([3, 2, 1, 7, 4, 5, 5, 9, 1])

df = pd.DataFrame({'group': group_idx, 'values': a})
df
#   group  values
#0      3       3
#1      2       2
#2      3       1
#3      2       7
#4      2       4
#5      1       5
#6      2       5
#7      1       9
#8      1       1

要获取按组和值排序的数据帧(在组中):

代码语言:javascript
复制
df.sort_values(["group", "values"])

#   group  values
#8      1       1
#5      1       5
#7      1       9
#1      2       2
#4      2       4
#6      2       5
#3      2       7
#2      3       1
#0      3       3

要按降序对值进行排序,请使用ascending = False。要对不同的列应用不同的顺序,您可以提供一个列表:

代码语言:javascript
复制
df.sort_values(["group", "values"], ascending = [True, False])

#   group  values
#7      1       9
#5      1       5
#8      1       1
#3      2       7
#6      2       5
#4      2       4
#1      2       2
#0      3       3
#2      3       1

在这里,组按升序排序,每个组中的值按降序排序。

要仅对属于同一组的连续行的值进行排序,请创建新的组指示器:

(我把这篇文章放在这里作为参考,因为它可能对其他人有帮助。在OP在评论中澄清他的问题之前,我在较早的版本中写了这篇文章。)

代码语言:javascript
复制
df['new_grp'] = (df.group.diff(1) != 0).astype('int').cumsum()
df
#   group  values  new_grp
#0      3       3        1
#1      2       2        2
#2      3       1        3
#3      2       7        4
#4      2       4        4
#5      1       5        5
#6      2       5        6
#7      1       9        7
#8      1       1        7

然后,我们可以轻松地使用new_grp而不是group进行排序,保持组的原始顺序不变。

在组内排序,但保留特定于组的行位置:

要对每个组的元素进行排序,但要保留数据帧中特定于组的位置,我们需要跟踪原始行号。例如,下面的代码就可以解决这个问题:

代码语言:javascript
复制
# First, create an indicator for the original row-number:

df["ind"] = range(len(df))

# Now, sort the dataframe as before
df_sorted = df.sort_values(["group", "values"])

# sort the original row-numbers within each group
newindex = df.groupby("group").apply(lambda x: x.sort_values(["ind"]))["ind"].values

# assign the sorted row-numbers to the sorted dataframe
df_sorted["ind"] = newindex

# Sort based on the row-numbers:
sorted_asc = df_sorted.sort_values("ind")

# compare the resulting order of values with your desired output:
np.array(sorted_asc["values"])
# array([1, 2, 3, 4, 5, 1, 7, 5, 9])

在函数中编写时,这更容易测试和分析,所以让我们这样做:

代码语言:javascript
复制
def sort_my_frame(frame, groupcol = "group", valcol = "values", asc = True):

    frame["ind"] = range(len(frame))
    frame_sorted = frame.sort_values([groupcol, valcol], ascending = [True, asc])
    ind_sorted = frame.groupby(groupcol).apply(lambda x: x.sort_values(["ind"]))["ind"].values
    frame_sorted["ind"] = ind_sorted
    frame_sorted = frame_sorted.sort_values(["ind"])

    return(frame_sorted.drop(columns = "ind"))

np.array(sort_my_frame(df, "group", "values", asc = True)["values"])
# array([1, 2, 3, 4, 5, 1, 7, 5, 9])
np.array(sort_my_frame(df, "group", "values", asc = False)["values"])
# array([3, 7, 1, 5, 4, 9, 2, 5, 1])

请注意,后一种结果与您期望的结果相匹配。

我相信这可以用一种更简洁的方式写出来。例如,如果您的dataframe的索引已经排序,您可以使用该索引而不是我创建的指示器ind (即,在@DJK的注释之后,我们可以使用sort_index而不是sort_values,从而避免分配额外的列)。在任何情况下,上面都强调了一种可能的解决方案以及如何接近它。另一种方法是使用numpy函数并将输出包装在pd.DataFrame中。

票数 5
EN

Stack Overflow用户

发布于 2018-04-28 18:43:34

熊猫是建立在numpy之上的。假设数据帧是这样的:

代码语言:javascript
复制
df
Out[21]: 
   group  values
0      3       3
1      2       2
2      3       1
3      2       7
4      2       4
5      1       5
6      2       5
7      1       9
8      1       1

调用你的函数。

代码语言:javascript
复制
groupwise_sort(df.group.values, df['values'].values)
Out[22]: array([1, 2, 3, 4, 5, 1, 7, 5, 9])

groupwise_sort(df.group.values, df['values'].values, reverse=True)
Out[23]: array([3, 7, 1, 5, 4, 9, 2, 5, 1])
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49968316

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档