在预排序的DataFrame上使用pandas groupby的迭代顺序

7

情况说明

我正在使用某个分类器根据特定列中的值对DataFrame中的行进行分类。我的目标是根据某些条件将结果附加到一个新列或另一个新列中。当前的代码大致如下:

df = pd.DataFrame({'A': [list with classifier ids],  # Only 3 ids, One word strings
                   'B': [List of text to be classified],  # Millions of unique rows, lines of text around 5-25 words long
                   'C': [List of the old classes]}  # Hundreds of possible classes, four digit integers stored as strings

df.sort_values('A', inplace=True)

new_col1, new_col2 = [], []
for name, group in df.groupby('A', sort=False):
    classifier = classy_dict[name]
    vectors = vectorize(group.B.values)

    preds = classifier.predict(vectors)
    scores = classifier.decision_function(vectors)

    for tup in zip(preds, scores, group.C.values):
        if tup[2] == tup[0]:
            new_col1.append(np.nan)
            new_col2.append(tup[2])

        else:
            new_col1.append(str(classifier.classes_[tup[1].argsort()[-5:]]))
            new_col2.append(np.nan)

df['D'] = new_col1
df['E'] = new_col2

问题

我担心groupby不会按照我期望的从上到下、按出现顺序迭代。当sort=False时,迭代顺序没有在文档中进行解释。

我的期望

我想确认一下groupby('col', sort=False)是否按照我期望的从上到下、按出现顺序迭代。如果有更好的方法来使所有内容正常工作,欢迎提出建议。

这是我用来测试关于sort=False迭代顺序理论的代码:

from numpy.random import randint
import pandas as pd
from string import ascii_lowercase as lowers

df = pd.DataFrame({'A': [lowers[randint(3)] for _ in range(100)],
                   'B': randint(10, size=100)})

print(df.A.unique())  # unique values in order of appearance per the docs

for name, group in df.groupby('A', sort=False):
    print(name)

编辑:上述代码使其看起来以我所期望的方式运作,但如果有确凿的证据,我希望能得到更多证明。

请注意,这里的“appear”是指表面上看起来如此,但并不确定是否确实如此。

我们希望看到您的实际数据和期望输出。这里的文本太多了。 - cs95
由于问题特别涉及到 groupby 函数的操作,实际数据与其无关。我已经简化了问题描述,并添加了数据样本说明。 - Eric Ed Lohmar
2个回答

9
是的,当您传递sort=False时,首次出现的顺序会被保留。 groupby 的源代码有点不透明,但有一个函数groupby.ngroup可以完全回答这个问题,因为它直接告诉您迭代发生的顺序。
def ngroup(self, ascending=True):
    """
    Number each group from 0 to the number of groups - 1.
    This is the enumerative complement of cumcount.  Note that the
    numbers given to the groups match the order in which the groups
    would be seen when iterating over the groupby object, not the
    order they are first observed.
    ""

来自@coldspeed的数据

df['sort=False'] = df.groupby('col', sort=False).ngroup()
df['sort=True'] = df.groupby('col', sort=True).ngroup()

输出:

    col  sort=False  sort=True
0   16           0          7
1    1           1          0
2   10           2          5
3   20           3          8
4    3           4          2
5   13           5          6
6    2           6          1
7    5           7          3
8    7           8          4

sort=False 时,按照第一次出现的顺序进行迭代;当 sort=True 时,对分组进行排序后再迭代。


1

让我们进行一次小型的实证测试。您可以迭代groupby并查看组的迭代顺序。

df

   col
0   16
1    1
2   10
3   20
4    3
5   13
6    2
7    5
8    7

for c, g in df.groupby('col', sort=False):
      print(c)  

16
1
10
20
3
13
2
5
7

看起来顺序被保留了。


我的关注点是你回答中出现的术语“appears”。如果您多次迭代set,它可能会巧合地按相同顺序运行,从而看起来是一致的,但不能依赖它。我正在寻找某种证明或文档,以确保它以我期望的方式执行,这是不可否认的。由于我有85%的把握认为这个问题是由咖啡因驱动的偏执狂引起的,而且您很友善地回答了,如果明天此时没有更好的答案,我将接受您的答案。 - Eric Ed Lohmar
我也打算编辑我的问题,以使我的期望更加明确。 - Eric Ed Lohmar
1
基于这个 https://github.com/pandas-dev/pandas/issues/8588,看起来他们添加了保留顺序的功能,所以是的,它被保留了。 - cs95
请注意,我认为它是指组之间的顺序,而不是组内部分的顺序。 - cs95
@EricEdLohmar 哦,恐怕我不确定后者。 - cs95
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接