簡體   English   中英

對獨立於列的每行絕對值以及列名進行排序

[英]Sort each row absolute value independent of columns along with column names

我有一個類似格式的數據框:

df = pd.DataFrame({
 'p1': [0, 0, 1, 1, -2],
 'p2': [9, 2, 3, -5, 3],
 'p3': [1, 3, 10, 3, 7],
 'p4': [4, 4, 7, 1, 10]})

    p1  p2  p3  p4
0   0   9   1   4
1   0   2   3   4
2   1   3   10  7
3   1   -5  3   1
4   -2  3   7   10

預期 output:

top1    top2
p2:9    p4:4
p4:4    p3:3
p3:10   p4:7
p2:-5   p3:3
p4:10   p3:7

通過大量研究,我能夠排序並獲得排序數組的索引。 我還能夠用列替換索引。 但我無法將它們與行值連接起來。

nlargest = 3
order = np.argsort(-df.abs().values, axis=1)[:, :nlargest]
result = pd.DataFrame(df.columns[order], 
                      columns=['top{}'.format(i) for i in range(1, nlargest+1)])

  top1 top2 top3
0   p2   p4   p3
1   p4   p3   p2
2   p3   p4   p2
3   p2   p3   p1
4   p4   p3   p2

使用上述方法,我嘗試對不同 DataFrame 中的行進行排序,后來想到將它們連接起來。 但我找不到正確的方法來做到這一點。 我知道這不是最佳方式。

result2 = pd.DataFrame(np.sort(df.values, axis=0), index=df.index, columns=df.columns)
result2 = result2.iloc[:, 0:nlargest]
result2.columns = columns=['top{}'.format(i) for i in range(1, nlargest+1)]

   top1  top2  top3
0    -2    -5     1
1     0     2     3
2     0     3     3
3     1     3     7
4     1     9    10

請幫助我更正排序和獲得預期格式的最短方法。

使用DataFrame.transformDataFrame.lookup

result = result.transform(lambda s: s + ':' + df.lookup(s.index, s).astype(str))

# print(result)
    top1  top2  top3
0   p2:9  p4:4  p3:1
1   p4:4  p3:3  p2:2
2  p3:10  p4:7  p2:3
3  p2:-5  p3:3  p1:1
4  p4:10  p3:7  p2:3

僅用於獲得最佳性能 numpy 解決方案:

nlargest = 3
arr = df.to_numpy()
order = np.argsort(-np.abs(arr), axis=1)[:, :nlargest]
print (order)
[[1 3 2]
 [3 2 1]
 [2 3 1]
 [1 2 0]
 [3 2 1]]

想法是按order數組更改 numpy 數組arr中的原始數據順序,如下所示

a = arr[np.arange(arr.shape[0])[:, None], order]
print (a)
[[ 9  4  1]
 [ 4  3  2]
 [10  7  3]
 [-5  3  1]
 [10  7  3]]

因此,您可以添加轉換為字符串的值:

result = pd.DataFrame(df.columns[order] + ':' + a.astype(str), 
                      columns=['top{}'.format(i) for i in range(1, nlargest+1)])

print (result)
    top1  top2  top3
0   p2:9  p4:4  p3:1
1   p4:4  p3:3  p2:2
2  p3:10  p4:7  p2:3
3  p2:-5  p3:3  p1:1
4  p4:10  p3:7  p2:3

由於您需要創建字符串,我們可以使用.stack.groupby.cumcount來獲取前 n 個值。

largest_n = 3

s = (
    df.stack()
    .sort_values(ascending=False)
    .groupby(level=0)
    .head(largest_n)
    .reset_index(1)
    .astype(str)
    .agg(":".join, axis=1)
    .to_frame("vals")
)

df1 = (
    (
        s.assign(key=s.groupby(level=0).cumcount() + 1)
        .set_index("key", append=True)
        .unstack()
    )
    .add_prefix("Top_")
    .droplevel(level=0, axis=1)
)

print(df1)

key  Top_1 Top_2 Top_3
0     p2:9  p4:4  p3:1
1     p4:4  p3:3  p2:2
2    p3:10  p4:7  p2:3
3     p3:3  p1:1  p4:1
4    p4:10  p3:7  p2:3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM