pandas dataframe,按另一列中的值排序,而不使用Python FOR循环
对于一列中的每个值(我下面的示例中的“日期”),我希望根据另一列中的值(我的示例中的“值”列)进行排名 我的代码可以工作,但我想知道如果没有Pythonfor循环,它是否可以完成pandas dataframe,按另一列中的值排序,而不使用Python FOR循环,python,pandas,dataframe,Python,Pandas,Dataframe,对于一列中的每个值(我下面的示例中的“日期”),我希望根据另一列中的值(我的示例中的“值”列)进行排名 我的代码可以工作,但我想知道如果没有Pythonfor循环,它是否可以完成 data = {'code': ['AAA', 'AAA', 'AAA', 'BBB', 'BBB', 'BBB', 'CCC', 'CCC', 'CCC'], 'date': ['2001-01-01', '2001-01-02', '2001-01-03', '2001-01-01', '2001-
data = {'code': ['AAA', 'AAA', 'AAA', 'BBB', 'BBB', 'BBB', 'CCC', 'CCC', 'CCC'],
'date': ['2001-01-01', '2001-01-02', '2001-01-03', '2001-01-01', '2001-01-02', '2001-01-03', '2001-01-01', '2001-01-02', '2001-01-03'],
'value': [32, 23, 34, 23, 34, 12, 28, 39, 40]}
df = pd.DataFrame(data)
print(df)
pd.set_option('mode.chained_assignment', None)
result = pd.DataFrame()
for date in df['date'].unique():
sub = df[df['date'] == date]
sub['rank'] = len(sub) - sub['value'].rank() + 1
result = result.append(sub[['code', 'date', 'rank']])
pd.set_option('mode.chained_assignment', 'warn')
df2 = pd.merge(df, result, on=['code', 'date'])
print(df2.sort_values(['date', 'code'])) # within each date, rows are ranked by value
我能在不迭代Python for循环的情况下得到相同的结果吗?让我们使用
groupby
进行rank
df['rank'] = df.groupby('code')['value'].rank()
df
Out[491]:
code date value rank
0 AAA 2001-01-01 32 2.0
1 AAA 2001-01-02 23 1.0
2 AAA 2001-01-03 34 3.0
3 BBB 2001-01-01 23 2.0
4 BBB 2001-01-02 34 3.0
5 BBB 2001-01-03 12 1.0
6 CCC 2001-01-01 28 1.0
7 CCC 2001-01-02 39 2.0
8 CCC 2001-01-03 40 3.0
让我们用
groupby
进行rank
,然后
df['rank'] = df.groupby('code')['value'].rank()
df
Out[491]:
code date value rank
0 AAA 2001-01-01 32 2.0
1 AAA 2001-01-02 23 1.0
2 AAA 2001-01-03 34 3.0
3 BBB 2001-01-01 23 2.0
4 BBB 2001-01-02 34 3.0
5 BBB 2001-01-03 12 1.0
6 CCC 2001-01-01 28 1.0
7 CCC 2001-01-02 39 2.0
8 CCC 2001-01-03 40 3.0
argsort
创造性地使用
def rank(s):
n = len(s)
a = s.to_numpy().argsort()
b = np.empty_like(a)
b[a] = np.arange(n)
return b + 1
df.assign(rank=df.groupby('code').value.transform(rank))
code date value rank
0 AAA 2001-01-01 32 2
1 AAA 2001-01-02 23 1
2 AAA 2001-01-03 34 3
3 BBB 2001-01-01 23 2
4 BBB 2001-01-02 34 3
5 BBB 2001-01-03 12 1
6 CCC 2001-01-01 28 1
7 CCC 2001-01-02 39 2
8 CCC 2001-01-03 40 3
lexsort
和unique
更具创造性,不再需要groupby
这应该很快。我必须在更大的数据上进行测试
def rank_grouped(s, groups):
n = len(s)
x = s.to_numpy()
y = groups.to_numpy()
a = np.lexsort([x, y])
b = np.empty_like(a)
r = np.arange(n)
t, i, j = np.unique(y[a], return_inverse=True, return_index=True)
b[a] = r - i[j] + 1
return b
df.assign(rank=rank_grouped(df.value, df.code))
code date value rank
0 AAA 2001-01-01 32 2
1 AAA 2001-01-02 23 1
2 AAA 2001-01-03 34 3
3 BBB 2001-01-01 23 2
4 BBB 2001-01-02 34 3
5 BBB 2001-01-03 12 1
6 CCC 2001-01-01 28 1
7 CCC 2001-01-02 39 2
8 CCC 2001-01-03 40 3
时机 大数据集
np.random.seed([3, 14])
n = 1_000_000
df = pd.DataFrame({
'code': np.random.randint(10_000, size=n),
'value': np.random.randn(n)
})
%timeit df.assign(rank=df.groupby('code').value.transform(rank))
%timeit df.assign(rank=df.groupby('code')['value'].rank())
%timeit df.assign(rank=rank_grouped(df.value, df.code))
1.29 s ± 7.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
367 ms ± 3.46 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
294 ms ± 2.32 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
argsort
创造性地使用
def rank(s):
n = len(s)
a = s.to_numpy().argsort()
b = np.empty_like(a)
b[a] = np.arange(n)
return b + 1
df.assign(rank=df.groupby('code').value.transform(rank))
code date value rank
0 AAA 2001-01-01 32 2
1 AAA 2001-01-02 23 1
2 AAA 2001-01-03 34 3
3 BBB 2001-01-01 23 2
4 BBB 2001-01-02 34 3
5 BBB 2001-01-03 12 1
6 CCC 2001-01-01 28 1
7 CCC 2001-01-02 39 2
8 CCC 2001-01-03 40 3
lexsort
和unique
更具创造性,不再需要groupby
这应该很快。我必须在更大的数据上进行测试
def rank_grouped(s, groups):
n = len(s)
x = s.to_numpy()
y = groups.to_numpy()
a = np.lexsort([x, y])
b = np.empty_like(a)
r = np.arange(n)
t, i, j = np.unique(y[a], return_inverse=True, return_index=True)
b[a] = r - i[j] + 1
return b
df.assign(rank=rank_grouped(df.value, df.code))
code date value rank
0 AAA 2001-01-01 32 2
1 AAA 2001-01-02 23 1
2 AAA 2001-01-03 34 3
3 BBB 2001-01-01 23 2
4 BBB 2001-01-02 34 3
5 BBB 2001-01-03 12 1
6 CCC 2001-01-01 28 1
7 CCC 2001-01-02 39 2
8 CCC 2001-01-03 40 3
时机 大数据集
np.random.seed([3, 14])
n = 1_000_000
df = pd.DataFrame({
'code': np.random.randint(10_000, size=n),
'value': np.random.randn(n)
})
%timeit df.assign(rank=df.groupby('code').value.transform(rank))
%timeit df.assign(rank=df.groupby('code')['value'].rank())
%timeit df.assign(rank=rank_grouped(df.value, df.code))
1.29 s ± 7.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
367 ms ± 3.46 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
294 ms ± 2.32 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
对我来说似乎是一个很好的答案(-:查看我的第二个答案。我很自豪,但必须对它进行压力测试。@piRSquared很好的解决方案,先生,第二个应该比argsort快~!明白了!也发布了时间安排。现在我只需要试着记住它。对我来说似乎是一个很好的答案(:查看我的第二个答案。我很自豪,但必须对它进行压力测试。@piRSquared很好的解决方案,先生,第二个应该比argsort快!明白了!也发布了时间安排。现在我只需要试着记住它。奖励教程打开。转换(排名)非常感谢奖励教程打开。转换(排名)非常感谢奖励教程打开