我想按多列對熊貓框架進行排序。我的約束讓我遇到了麻煩,其中一列(第一列)需要自然排序,所以我嘗試了以下方法:
sortedFrame = inFrame.sort_values(by=['Col_Arg', 'Col_Step'],
key=lambda x:np.argsort(index_natsorted(inFrame['Col_Arg'])))
但此代碼導致框架僅按 Col_Arg 排序。例如輸入幀
| Col_Arg | Col_Step |
|---|---|
| 1 第一 | 20 |
| 2 秒 | 10 |
| 1 第一 | 10 |
結果是
| Col_Arg | Col_Step |
|---|---|
| 1 第一 | 20 |
| 1 第一 | 10 |
| 2 秒 | 10 |
您可以將 Col_Arg 想象為索引標題。在該索引標題內是要執行的步驟 (Col_2)。由于 Col_Arg 是一個無法轉換為整數的字串,因此我想使用 natsort,它可以很好地單獨為 Col_Arg 排序,但不適用于多個列名。簡單的方法就是為標題引入一個額外的索引。然后我可以很容易地使用:
sortedFrame = inFrame.sort_values(['Col_Arg_Idx', 'Col_2'])
因為我對 python 和 pandas 很陌生,所以我很好奇,我想了解我的誤解是什么以及你會怎么做,因為我認為我應該是可能的。我可以想象它與密鑰的使用有關:
key: keycallable, optional 在排序前對值應用key函式。這類似于內置 sorted() 函式中的 key 引數,但顯著的區別是這個 key 函式應該是矢量化的。它應該期望一個系列并回傳一個與輸入具有相同形狀的系列。它將獨立應用于 by 中的每一列。
但這并不意味著它適用于所有......我有點困惑。
為了后面引入中間步驟,索引最初從 10 開始遞增 10。
提前致謝。
uj5u.com熱心網友回復:
因此,您的代碼的問題在于,當您pandas.DataFrame.sort_values在引數旁邊使用多個列時key,pandas 按照您在引數中定義的順序獲取每個系列,并呼叫該函式,按照它們在呼叫之前出現的順序by=["col1", "col2"]將列值傳遞給它.sort_values
例如,讓我們定義一個簡單的函式,它只列印它接收到的引數,并將其用作我們的key引數:
import pandas as pd
import numpy as np
from natsort import index_natsorted, natsort_keygen, natsorted
# == Sample DataFrame ============================
df = pd.DataFrame(
{
'Col_Arg': ['First', 'Second', 'First', 'Third', 'Fourth', 'Tenth'],
'Col_Step': [20, 10, 10, 30, 20, 5]
}
)
# == Simple Key Function ============================
def print_values(x):
print(x)
return x
df.sort_values(
by=["Col_Arg", "Col_Step"],
key=lambda x: print_values(x)
)
# Returns:
"""
0 1 First
1 2 Second
2 1 First
3 3 Third
4 4 Fourth
5 10 Tenth
Name: Col_Arg, dtype: object
0 20
1 10
2 10
3 30
4 20
5 5
Name: Col_Step, dtype: int64
"""
所以基本上pandas.DataFrame.sort_values將每一列作為一個系列傳遞給您的函式,并且它希望您的函式進行一些轉換以使列“可排序”。以下是 pandas 檔案中的引數描述:
key: callable, 可選
描述:
在排序之前將key函式應用于值。這類似于內置sorted()函式中的 key 引數,顯著的區別是這個 key 函式應該被矢量化。它應該期望一個系列并回傳一個與輸入具有相同形狀的系列。它將獨立應用于 by 中的每一列。
換句話說,如果要在同一pandas.DataFrame.sort_values操作中對兩列進行排序,則需要傳入一個能夠轉換'Col_Arg'為數字形式的函式,同時不加'Col_Step'修改地回傳。此外,通過使用inFrameinkey=lambda x:np.argsort(index_natsorted(inFrame['Col_Arg']))而不是傳遞x,鍵函式將根據inFrame索引在呼叫函式之前存在的順序對值進行排序。sort_values這是一個例子:
df.sort_values(
by=["Col_Arg", "Col_Step"],
key=lambda x: print_values(np.argsort(index_natsorted(df["Col_Step"])))
)
# Prints:
"""
[3 1 2 5 4 0]
[3 1 2 5 4 0]
"""
因此,第一次key呼叫該函式時,它使用 對資料幀索引進行排序[3 1 2 5 4 0],然后它應用與以前相同的順序,但現在所有索引都已移動,因此最終破壞了排序操作。
快速解決
如前所述,該key函式按照它們在排序操作之前存在的順序獲取每個列值。所以我們需要創建一個將'Col_Arg'值轉換為數字的函式,而不是嘗試在 key 函式內部進行排序。有一個名為number-parser的包可以為你做這件事。要安裝它,請運行以下代碼:
pip install number-parser
然后,您可以創建一個在內部使用的函式,key如下所示:
import numpy as np
import pandas as pd
from number_parser import parse_ordinal
def custom_sort(col: pd.Series) -> pd.Series:
if col.name == "Col_Arg":
return col.apply(parse_ordinal)
return col
df.sort_values(
by=["Col_Arg", "Col_Step"],
key=custom_sort
)
# Returns:
"""
Col_Arg Col_Step
2 First 10
0 First 20
1 Second 10
3 Third 30
4 Fourth 20
5 Tenth 5
"""
解決方案 2:另一種選擇是執行以下操作:
import pandas as pd
import numpy as np
from natsort import index_natsorted, natsort_keygen, natsorted
df.sort_values(
by="Col_Arg", key=lambda col: np.argsort(index_natsorted(col))
).groupby("Col_Arg", as_index=False).apply(
lambda grp: grp.sort_values("Col_Step")
).reset_index(
drop=True
)
# Returns:
"""
Col_Arg Col_Step
0 First 10
1 First 20
2 Fourth 20
3 Second 10
4 Tenth 5
5 Third 30
"""
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/514768.html
上一篇:無法對偶數后跟奇數的陣列進行排序
