如何在巨大数据帧的每一行中找到前 n 个值的列索引
How to find column-index of top-n values within each row of huge dataframe
我有一个格式的数据框:(示例数据)
Metric1 Metric2 Metric3 Metric4 Metric5
ID
1 0.5 0.3 0.2 0.8 0.7
2 0.1 0.8 0.5 0.2 0.4
3 0.3 0.1 0.7 0.4 0.2
4 0.9 0.4 0.8 0.5 0.2
其中分数范围在 [0,1] 之间,我希望生成一个函数,该函数针对每个 id(行)计算前 n 个指标,其中 n 是函数的输入以及原始数据帧。
我理想的输出是:(例如 n = 3)
Top_1 Top_2 Top_3
ID
1 Metric4 Metric5 Metric1
2 Metric2 Metric3 Metric5
3 Metric3 Metric4 Metric1
4 Metric1 Metric3 Metric4
现在我写了一个可以工作的函数:
def top_n_partners(scores,top_n=3):
metrics = np.array(scores.columns)
records=[]
for rec in scores.to_records():
rec = list(rec)
ID = rec[0]
score_vals = rec[1:]
inds = np.argsort(score_vals)
top_metrics = metrics[inds][::-1]
dic = {
'top_score_%s' % (i+1):top_metrics[i]
for i in range(top_n)
}
dic['ID'] = ID
records.append(dic)
top_n_df = pd.DataFrame(records)
top_n_df.set_index('ID',inplace=True)
return top_n_df
然而,它似乎相当 inefficient/slow 特别是对于我要 运行 的数据量(具有数百万行的数据框),我想知道是否有更聪明的方法关于这个?
您可以使用 numpy.argsort
:
print (np.argsort(-df.values, axis=1)[:,:3])
[[3 4 0]
[1 2 4]
[2 3 0]
[0 2 3]]
print (df.columns[np.argsort(-df.values, axis=1)[:,:3]])
Index([['Metric4', 'Metric5', 'Metric1'], ['Metric2', 'Metric3', 'Metric5'],
['Metric3', 'Metric4', 'Metric1'], ['Metric1', 'Metric3', 'Metric4']],
dtype='object')
df = pd.DataFrame(df.columns[np.argsort(-df.values, axis=1)[:,:3]],
index=df.index)
df = df.rename(columns = lambda x: 'Top_{}'.format(x + 1))
print (df)
Top_1 Top_2 Top_3
ID
1 Metric4 Metric5 Metric1
2 Metric2 Metric3 Metric5
3 Metric3 Metric4 Metric1
4 Metric1 Metric3 Metric4
感谢 改进:
n = 3
df = pd.DataFrame(df.columns[df.values.argsort(1)[:,-n+2:1:-1]],
index=df.index)
df = df.rename(columns = lambda x: 'Top_{}'.format(x + 1))
print (df)
Top_1 Top_2 Top_3
ID
1 Metric4 Metric5 Metric1
2 Metric2 Metric3 Metric5
3 Metric3 Metric4 Metric1
4 Metric1 Metric3 Metric4
使用 Pandas 重塑的不同方式:
df.set_index('ID', inplace=True)
df_out = df.rank(axis=1, ascending=False).astype(int).reset_index().melt(id_vars='ID').query('value <= 3').pivot(index='ID',columns='value')
df_out.columns = df_out.columns.droplevel().astype(str)
df_out = df_out.add_prefix('Top_')
print(df_out)
输出:
value Top_1 Top_2 Top_3
ID
1 Metric4 Metric5 Metric1
2 Metric2 Metric3 Metric5
3 Metric3 Metric4 Metric1
4 Metric1 Metric3 Metric4
我有一个格式的数据框:(示例数据)
Metric1 Metric2 Metric3 Metric4 Metric5
ID
1 0.5 0.3 0.2 0.8 0.7
2 0.1 0.8 0.5 0.2 0.4
3 0.3 0.1 0.7 0.4 0.2
4 0.9 0.4 0.8 0.5 0.2
其中分数范围在 [0,1] 之间,我希望生成一个函数,该函数针对每个 id(行)计算前 n 个指标,其中 n 是函数的输入以及原始数据帧。
我理想的输出是:(例如 n = 3)
Top_1 Top_2 Top_3
ID
1 Metric4 Metric5 Metric1
2 Metric2 Metric3 Metric5
3 Metric3 Metric4 Metric1
4 Metric1 Metric3 Metric4
现在我写了一个可以工作的函数:
def top_n_partners(scores,top_n=3):
metrics = np.array(scores.columns)
records=[]
for rec in scores.to_records():
rec = list(rec)
ID = rec[0]
score_vals = rec[1:]
inds = np.argsort(score_vals)
top_metrics = metrics[inds][::-1]
dic = {
'top_score_%s' % (i+1):top_metrics[i]
for i in range(top_n)
}
dic['ID'] = ID
records.append(dic)
top_n_df = pd.DataFrame(records)
top_n_df.set_index('ID',inplace=True)
return top_n_df
然而,它似乎相当 inefficient/slow 特别是对于我要 运行 的数据量(具有数百万行的数据框),我想知道是否有更聪明的方法关于这个?
您可以使用 numpy.argsort
:
print (np.argsort(-df.values, axis=1)[:,:3])
[[3 4 0]
[1 2 4]
[2 3 0]
[0 2 3]]
print (df.columns[np.argsort(-df.values, axis=1)[:,:3]])
Index([['Metric4', 'Metric5', 'Metric1'], ['Metric2', 'Metric3', 'Metric5'],
['Metric3', 'Metric4', 'Metric1'], ['Metric1', 'Metric3', 'Metric4']],
dtype='object')
df = pd.DataFrame(df.columns[np.argsort(-df.values, axis=1)[:,:3]],
index=df.index)
df = df.rename(columns = lambda x: 'Top_{}'.format(x + 1))
print (df)
Top_1 Top_2 Top_3
ID
1 Metric4 Metric5 Metric1
2 Metric2 Metric3 Metric5
3 Metric3 Metric4 Metric1
4 Metric1 Metric3 Metric4
感谢
n = 3
df = pd.DataFrame(df.columns[df.values.argsort(1)[:,-n+2:1:-1]],
index=df.index)
df = df.rename(columns = lambda x: 'Top_{}'.format(x + 1))
print (df)
Top_1 Top_2 Top_3
ID
1 Metric4 Metric5 Metric1
2 Metric2 Metric3 Metric5
3 Metric3 Metric4 Metric1
4 Metric1 Metric3 Metric4
使用 Pandas 重塑的不同方式:
df.set_index('ID', inplace=True)
df_out = df.rank(axis=1, ascending=False).astype(int).reset_index().melt(id_vars='ID').query('value <= 3').pivot(index='ID',columns='value')
df_out.columns = df_out.columns.droplevel().astype(str)
df_out = df_out.add_prefix('Top_')
print(df_out)
输出:
value Top_1 Top_2 Top_3
ID
1 Metric4 Metric5 Metric1
2 Metric2 Metric3 Metric5
3 Metric3 Metric4 Metric1
4 Metric1 Metric3 Metric4