对多行数据框中的行值进行排名
Ranking row values from a multiplus row dataframe
我有一个巨大的 df
,看起来像这样:
date
stock1
stock2
stock3
stock4
stock5
stock6
stock7
stock8
stock9
stock10
10/20
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
0.9
11/20
0.8
0.9
0.3
0.4
0.3
0.5
0.3
0.2
0.4
0.1
12/20
0.3
0.6
0.9
0.5
0.6
0.7
0.8
0.7
0.9
0.1
我想为每一行找出股票价值高 20% 和低 20% 的股票。输出应该是:
date
higher
lower
10/20
stock9, stock 10
stock1, stock 2
11/20
stock1, stock 2
stock8, stock 10
12/20
stock3, stock 9
stock1, stock 10
我不需要在上面的值之间有逗号,可以一个在另一个下面。
我已尝试 df= df.stack()
进行堆叠,然后对列内的值进行排名,但我不知道如何进行。
您可以使用对每行的值进行排序的辅助函数来完成此操作:
def get_top_bottom_20_pct(x):
d = x.sort_values(ascending=False).index.tolist()
return [*map(', '.join, (d[:size], d[-size:]))]
size = int(0.2 * df.shape[1])
s = df.set_index('date').apply(get_top_bottom_20_pct, axis=1)
out = pd.DataFrame(s.tolist(), index=s.index, columns=['higher','lower']).reset_index()
如果你有 Python >=3.8,你可以用海象运算符做同样的事情:
s = df.set_index('date').apply(lambda x: (', '.join((d := x.sort_values(ascending=False).index.tolist())[:size]),
', '.join(d[-size:])), axis=1)
out = pd.DataFrame(s.tolist(), index=s.index, columns=['higher','lower']).reset_index()
输出:
date higher lower
0 10/20 stock9, stock10 stock2, stock1
1 11/20 stock2, stock1 stock8, stock10
2 12/20 stock3, stock9 stock1, stock10
试试 nlargest
和 nsmallest
:
#df = df.set_index("date") #uncomment if date is a column and not the index
n = round(len(df.columns)*0.2) #number of stocks in the top/bottom 20%
output = pd.DataFrame()
output["higher"] = df.apply(lambda x: x.nlargest(n).index.tolist(), axis=1)
output["lower"] = df.apply(lambda x: x.nsmallest(n).index.tolist(), axis=1)
>>> output
higher lower
date
10/20 [stock9, stock10] [stock1, stock2]
11/20 [stock2, stock1] [stock10, stock8]
12/20 [stock3, stock9] [stock10, stock1]
编辑:
如果您希望每个股票名称单独一行,您可以这样做:
output = pd.DataFrame()
output["higher"] = df.apply(lambda x: "\n".join(x.nlargest(n).index.tolist()), axis=1)
output["lower"] = df.apply(lambda x: "\n".join(x.nsmallest(n).index.tolist()), axis=1)
我有一个巨大的 df
,看起来像这样:
date | stock1 | stock2 | stock3 | stock4 | stock5 | stock6 | stock7 | stock8 | stock9 | stock10 |
---|---|---|---|---|---|---|---|---|---|---|
10/20 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 0.9 |
11/20 | 0.8 | 0.9 | 0.3 | 0.4 | 0.3 | 0.5 | 0.3 | 0.2 | 0.4 | 0.1 |
12/20 | 0.3 | 0.6 | 0.9 | 0.5 | 0.6 | 0.7 | 0.8 | 0.7 | 0.9 | 0.1 |
我想为每一行找出股票价值高 20% 和低 20% 的股票。输出应该是:
date | higher | lower |
---|---|---|
10/20 | stock9, stock 10 | stock1, stock 2 |
11/20 | stock1, stock 2 | stock8, stock 10 |
12/20 | stock3, stock 9 | stock1, stock 10 |
我不需要在上面的值之间有逗号,可以一个在另一个下面。
我已尝试 df= df.stack()
进行堆叠,然后对列内的值进行排名,但我不知道如何进行。
您可以使用对每行的值进行排序的辅助函数来完成此操作:
def get_top_bottom_20_pct(x):
d = x.sort_values(ascending=False).index.tolist()
return [*map(', '.join, (d[:size], d[-size:]))]
size = int(0.2 * df.shape[1])
s = df.set_index('date').apply(get_top_bottom_20_pct, axis=1)
out = pd.DataFrame(s.tolist(), index=s.index, columns=['higher','lower']).reset_index()
如果你有 Python >=3.8,你可以用海象运算符做同样的事情:
s = df.set_index('date').apply(lambda x: (', '.join((d := x.sort_values(ascending=False).index.tolist())[:size]),
', '.join(d[-size:])), axis=1)
out = pd.DataFrame(s.tolist(), index=s.index, columns=['higher','lower']).reset_index()
输出:
date higher lower
0 10/20 stock9, stock10 stock2, stock1
1 11/20 stock2, stock1 stock8, stock10
2 12/20 stock3, stock9 stock1, stock10
试试 nlargest
和 nsmallest
:
#df = df.set_index("date") #uncomment if date is a column and not the index
n = round(len(df.columns)*0.2) #number of stocks in the top/bottom 20%
output = pd.DataFrame()
output["higher"] = df.apply(lambda x: x.nlargest(n).index.tolist(), axis=1)
output["lower"] = df.apply(lambda x: x.nsmallest(n).index.tolist(), axis=1)
>>> output
higher lower
date
10/20 [stock9, stock10] [stock1, stock2]
11/20 [stock2, stock1] [stock10, stock8]
12/20 [stock3, stock9] [stock10, stock1]
编辑: 如果您希望每个股票名称单独一行,您可以这样做:
output = pd.DataFrame()
output["higher"] = df.apply(lambda x: "\n".join(x.nlargest(n).index.tolist()), axis=1)
output["lower"] = df.apply(lambda x: "\n".join(x.nsmallest(n).index.tolist()), axis=1)