使用pandas根据组内排序创建新列

时间:2015-01-25 14:43:40

标签: python algorithm numpy pandas aggregation

我有一个包含大量行的pandas DataFrame。我正在尝试根据成员的组内排名顺序为框架创建新列。以下是一些虚假数据,说明了我的内容:

Num_members = int(1.e7)
Num_groups = int(1.e5)
members = pd.DataFrame({
    'ID': np.arange(Num_members),
    'groupID': np.random.random_integers(0, 2*Num_groups, Num_members),
    'groupmass': np.zeros(Num_members), 
    'brightness': np.random.uniform(8,12, Num_members), 
    'color':np.random.uniform(0,1,Num_members)
})

我正在尝试为成员创建两个新列:

  • 组内秩序为亮度,使最亮 组的成员将获得 0 的值,下一个最亮的 1 等等。

  • 该组最亮的成员的颜色。因此,对于此列,同一组中的所有成员将被分配相同的值,该值等于'颜色'具有组内亮度等级= 0的成员。

我知道groupby操作是针对这种操作而设计的,但我还没有能够弄清楚如何正确地执行此操作。速度是一个重要问题,因为我的数据集很大,我需要在MCMC可能性分析中做到这一点。

2 个答案:

答案 0 :(得分:2)

这是我的玩具示例:

import pandas as pd
import numpy as np
numpy.random.seed(42)
Num_members = int(10)
Num_groups = int(1)
members = pd.DataFrame({
    'ID': np.arange(Num_members),
    'groupID': np.random.random_integers(0, 2*Num_groups, Num_members),
    'groupmass': np.zeros(Num_members), 
    'brightness': np.random.uniform(8,12, Num_members), 
    'color':np.random.uniform(0,1,Num_members)
})

使用自定义函数计算亮度的等级和最大值:

def rank_max_fun(df):
    df["b_rank"] = df.brightness.rank(ascending=False)
    df["b_max"] = df.brightness.max()
    return df

分组和应用

 df = members.groupby("groupID", sort=False).apply(rank_max_fun)

的产率:

    ID  brightness  color   groupID groupmass   b_rank  b_max
0   0   8.232334    0.304242    2   0   6   11.329771
1   1   11.464705   0.524756    0   0   2   11.879639
2   2   10.404460   0.431945    2   0   3   11.329771
3   3   10.832290   0.291229    2   0   2   11.329771
4   4   8.082338    0.611853    0   0   3   11.879639
5   5   11.879639   0.139494    0   0   1   11.879639
6   6   11.329771   0.292145    2   0   1   11.329771
7   7   8.849356    0.366362    1   0   1   8.849356
8   8   8.727300    0.456070    2   0   5   11.329771
9   9   8.733618    0.785176    2   0   4   11.329771

下行:大型数据集需要相当长的时间。

答案 1 :(得分:2)

我再试一次:

import pandas as pd
import numpy as np
np.random.seed(42)
Num_members = int(10)
Num_groups = int(1)
members = pd.DataFrame({
    'ID': np.arange(Num_members),
    'groupID': np.random.random_integers(0, 2*Num_groups, Num_members),
    'groupmass': np.zeros(Num_members), 
    'brightness': np.random.uniform(8,12, Num_members), 
    'color':np.random.uniform(0,1,Num_members)
})

逻辑:

df = members.groupby("groupID").agg({"brightness": np.max})
df = df.reset_index()
df = df.merge(members[["groupID", "brightness", "color"]], on=("groupID", "brightness"))

首先,我们进行分组以找到最大brightness值。之后,我们将dfmembers结合使用,以获得具有最高color值的成员的brightness值。基本上,我们合并了membersdf中具有相同brightnessgroupID值的所有行。

请注意,如果组中有多个具有最高分数的值,则可能会导致意外的行重复。

df现在看起来如下:

    groupID brightness  color
0   0   11.879639   0.139494
1   1   8.849356    0.366362
2   2   11.329771   0.292145

对于每个组,它包含groupIDbrightness的最大值以及具有最大亮度值的元素的color

我们现在可以合并数据框membersdf

result = members.merge(df, on="groupID", suffixes=("_member", "_group"))

获得以下结果:

    ID  brightness_member   color_member    groupID groupmass   brightness_group    color_group
0   0   8.232334    0.304242    2   0   11.329771   0.292145
1   2   10.404460   0.431945    2   0   11.329771   0.292145
2   3   10.832290   0.291229    2   0   11.329771   0.292145
3   6   11.329771   0.292145    2   0   11.329771   0.292145
4   8   8.727300    0.456070    2   0   11.329771   0.292145
5   9   8.733618    0.785176    2   0   11.329771   0.292145
6   1   11.464705   0.524756    0   0   11.879639   0.139494
7   4   8.082338    0.611853    0   0   11.879639   0.139494
8   5   11.879639   0.139494    0   0   11.879639   0.139494
9   7   8.849356    0.366362    1   0   8.849356    0.366362