按另一个数据框中的列对 pandas DataFrame 进行排序 - pandas
Sort a pandas DataFrame by a column in another dataframe - pandas
假设我有一个包含两列的 Pandas DataFrame,例如:
df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [100, 200, 300, 400]})
print(df)
a b
0 1 100
1 2 200
2 3 300
3 4 400
假设我也有一个 Pandas 系列,例如:
s = pd.Series([1, 3, 2, 4])
print(s)
0 1
1 3
2 2
3 4
dtype: int64
如何将 a
列排序为与 s
系列相同的顺序,并将相应的行值排序在一起?
我想要的输出是:
a b
0 1 100
1 3 300
2 2 200
3 4 400
有什么办法可以实现吗?
请检查下面的自我回答。
我经常 运行 遇到这些问题,所以我只是想在 Pandas 中分享我的解决方案。
解决方案:
方案一:
使用set_index
将a
列转换为索引,然后使用reindex
更改顺序,然后使用rename_axis
将索引名称改回a
,然后使用 reset_index
将 a
列从索引转换回列:
print(df.set_index('a').reindex(s).rename_axis('a').reset_index('a'))
方案二:
使用set_index
将a
列转换为索引,然后使用loc
改变顺序,然后使用reset_index
转换a
列从一个索引回到一个列:
print(df.set_index('a').loc[s].reset_index())
方案三:
使用 iloc
以不同的顺序对行进行索引,然后使用 map
获取适合 df
的顺序,使其按 [=31] 排序=]系列:
print(df.iloc[list(map(df['a'].tolist().index, s))])
方案四:
使用 pd.DataFrame
创建一个新的 DataFrame 对象,然后使用 sorted
和 key
参数按 s
系列对 DataFrame 进行排序:
print(pd.DataFrame(sorted(df.values.tolist(), key=lambda x: s.tolist().index(x[0])), columns=df.columns))
时间安排:
使用以下代码计时:
import pandas as pd
from timeit import timeit
df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [100, 200, 300, 400]})
s = pd.Series([1, 3, 2, 4])
def u10_1():
return df.set_index('a').reindex(s).rename_axis('a').reset_index('a')
def u10_2():
return df.set_index('a').loc[s].reset_index()
def u10_3():
return df.iloc[list(map(df['a'].tolist().index, s))]
def u10_4():
return pd.DataFrame(sorted(df.values.tolist(), key=lambda x: s.tolist().index(x[0])), columns=df.columns)
print('u10_1:', timeit(u10_1, number=1000))
print('u10_2:', timeit(u10_2, number=1000))
print('u10_3:', timeit(u10_3, number=1000))
print('u10_4:', timeit(u10_4, number=1000))
输出:
u10_1: 3.012849470495621
u10_2: 3.072132612502147
u10_3: 0.7498072134665241
u10_4: 0.8109911930595484
@Allen 也有一个很好的答案。
怎么样:
(
df.assign(s=s)
.sort_values(by='s')
.drop('s', axis=1)
)
假设我有一个包含两列的 Pandas DataFrame,例如:
df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [100, 200, 300, 400]})
print(df)
a b
0 1 100
1 2 200
2 3 300
3 4 400
假设我也有一个 Pandas 系列,例如:
s = pd.Series([1, 3, 2, 4])
print(s)
0 1
1 3
2 2
3 4
dtype: int64
如何将 a
列排序为与 s
系列相同的顺序,并将相应的行值排序在一起?
我想要的输出是:
a b
0 1 100
1 3 300
2 2 200
3 4 400
有什么办法可以实现吗?
请检查下面的自我回答。
我经常 运行 遇到这些问题,所以我只是想在 Pandas 中分享我的解决方案。
解决方案:
方案一:
使用set_index
将a
列转换为索引,然后使用reindex
更改顺序,然后使用rename_axis
将索引名称改回a
,然后使用 reset_index
将 a
列从索引转换回列:
print(df.set_index('a').reindex(s).rename_axis('a').reset_index('a'))
方案二:
使用set_index
将a
列转换为索引,然后使用loc
改变顺序,然后使用reset_index
转换a
列从一个索引回到一个列:
print(df.set_index('a').loc[s].reset_index())
方案三:
使用 iloc
以不同的顺序对行进行索引,然后使用 map
获取适合 df
的顺序,使其按 [=31] 排序=]系列:
print(df.iloc[list(map(df['a'].tolist().index, s))])
方案四:
使用 pd.DataFrame
创建一个新的 DataFrame 对象,然后使用 sorted
和 key
参数按 s
系列对 DataFrame 进行排序:
print(pd.DataFrame(sorted(df.values.tolist(), key=lambda x: s.tolist().index(x[0])), columns=df.columns))
时间安排:
使用以下代码计时:
import pandas as pd
from timeit import timeit
df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [100, 200, 300, 400]})
s = pd.Series([1, 3, 2, 4])
def u10_1():
return df.set_index('a').reindex(s).rename_axis('a').reset_index('a')
def u10_2():
return df.set_index('a').loc[s].reset_index()
def u10_3():
return df.iloc[list(map(df['a'].tolist().index, s))]
def u10_4():
return pd.DataFrame(sorted(df.values.tolist(), key=lambda x: s.tolist().index(x[0])), columns=df.columns)
print('u10_1:', timeit(u10_1, number=1000))
print('u10_2:', timeit(u10_2, number=1000))
print('u10_3:', timeit(u10_3, number=1000))
print('u10_4:', timeit(u10_4, number=1000))
输出:
u10_1: 3.012849470495621
u10_2: 3.072132612502147
u10_3: 0.7498072134665241
u10_4: 0.8109911930595484
@Allen 也有一个很好的答案。
怎么样:
(
df.assign(s=s)
.sort_values(by='s')
.drop('s', axis=1)
)