【问题标题】:Pandas groupby.ngroup() in index order?Pandas groupby.ngroup() 按索引顺序排列?
【发布时间】:2021-01-07 03:40:10
【问题描述】:

Pandas groupby“ngroup”函数按“组”顺序标记每个组。

我正在寻找类似的行为,但需要分配的标签以原始(索引)顺序排列,我怎样才能在 pandas 和 numpy 中有效地做到这一点(这经常发生在大型数组中)?

> df = pd.DataFrame(
          {"A": [9,8,7,8,9]},
          index=list("abcde"))
   A
a  9
b  8
c  7
d  8
e  9
> df.groupby("A").ngroup()
a    2
b    1
c    0
d    1
e    2


# LOOKING FOR ###################
a    0
b    1
c    2
d    1
e    0

如何使用一维 numpy 数组实现所需的输出?

arr = np.array([9,8,7,8 ,9])
# looking for [0,1,2,1,0]

【问题讨论】:

    标签: python pandas numpy pandas-groupby


    【解决方案1】:

    也许更好的方法是factorize:

    df['A'].factorize()[0]
    

    输出:

    array([0, 1, 2, 1, 0])
    

    【讨论】:

    • 这种方法适用于 numpy 数组:pd.factorize(arr)[0] -> array([0, 1, 2, 1, 0], dtype=int64)
    • 太棒了!伙计们知道如何用 numpy (没有熊猫依赖)来完成吗?
    【解决方案2】:

    您可以将sort=Flase 传递给 groupby():

    df.groupby('A', sort=False).ngroup()
    
    a    0
    b    1
    c    2
    d    1
    e    0
    dtype: int64
    

    据我所知,numpy 中没有直接等效于 groupby 的内容。对于纯numpy 版本,您可以使用numpy.unique() 来获取唯一值。 numpy.unique() 可以选择返回逆,基本上是重新创建输入数组的索引数组,但它首先对唯一值进行排序,因此结果与使用常规(排序)pandas.groupby() 命令相同。

    要解决这个问题,您可以捕获每个唯一值第一次出现的索引值。对索引值进行排序并将它们用作原始数组的索引,以按原始顺序获取唯一值。创建一个字典以在唯一值和组号之间进行映射,然后使用该字典将数组中的值转换为适当的组号。

    import numpy as np
    
    arr = np.array([9, 8, 7, 8, 9])
    
    _, i = np.unique(arr, return_index=True)  # get the indexes of the first occurence of each unique value
    groups = arr[np.sort(i)]  # sort the indexes and retrieve the values from the array so that they are in the array order
    m = {value:ngroup for ngroup, value in enumerate(groups)}  # create a mapping of value:groupnumber
    np.vectorize(m.get)(arr)  # use vectorize to create a new array using m
    
    array([0, 1, 2, 1, 0])
    

    【讨论】:

    • 虽然@Quang 的答案中的因式分解方法要快得多,但这在对多列进行分组时也非常有用(即 df.groupby(["A", "B"], sort=False) ...)
    • @Amir - 请查看我的更新答案以获得纯 numpy 解决方案。
    【解决方案3】:

    你可以使用np.unique -

    In [105]: a = np.array([9,8,7,8 ,9])
    
    In [106]: u,idx, tags = np.unique(a, return_index=True, return_inverse=True)
    
    In [107]: idx.argsort().argsort()[tags]
    Out[107]: array([0, 1, 2, 1, 0])
    

    【讨论】:

    • 如果 a = np.array([12,10,11,12]) ,使用上面我们得到 (1,2,0,1) 而不是所需的 (0,1,2, 0)
    • 简单地 idx[tags] 也无济于事, a = np.array([12,10,10,11]) 我们得到 (0,1,1,3) 而不是期望的 (0 ,1,1,2)
    • @Amir 还需要一个。查看已编辑的解决方案。
    猜你喜欢
    • 2019-01-08
    • 1970-01-01
    • 2021-03-22
    • 2016-01-16
    • 2017-04-10
    • 2020-04-30
    • 2018-08-29
    • 1970-01-01
    • 2016-02-15
    相关资源
    最近更新 更多