在预先排序的 DataFrame 上使用 pandas groupby 的迭代顺序
Iteration order with pandas groupby on a pre-sorted DataFrame
情况
我正在使用基于特定列中的值的特定分类器对 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
未包含在 the docs
中时的迭代顺序
我的期望
我在这里寻找的只是一些确认 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)
编辑:上面的代码使它看起来好像它以我期望的方式运行,但我想要一些更不可否认的证据,如果它可用的话。
让我们做一个小的实证测试。您可以迭代 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
看来订单被保留了。
是的,当您通过 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
时对组进行排序,然后进行迭代。
情况
我正在使用基于特定列中的值的特定分类器对 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
未包含在 the docs
我的期望
我在这里寻找的只是一些确认 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)
编辑:上面的代码使它看起来好像它以我期望的方式运行,但我想要一些更不可否认的证据,如果它可用的话。
让我们做一个小的实证测试。您可以迭代 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
看来订单被保留了。
是的,当您通过 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
时对组进行排序,然后进行迭代。