重新排序 pandas 数据框中的行子集(重新索引)
reorder subset of rows in pandas dataframe (reindex)
使用
import pandas as pd
import numpy as np
鉴于此数据框,
df = pd.DataFrame(np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12],
[13, 14, 15],
[16, 17, 18],
[19, 20, 21]
]),
columns=['a', 'b', 'c'])
Out[1]:
a b c
0 1 2 3
1 4 5 6
2 7 8 9
3 10 11 12
4 13 14 15
5 16 17 18
6 19 20 21
我想重新排序并将第 2 到 5 行放回原位,
2 7 8 9
3 10 11 12
4 13 14 15
5 16 17 18
如果子集内的顺序是 [2,0,1,3]
,则期望的结果是,
Out[2]:
a b c
0 1 2 3
1 4 5 6
4 13 14 15
2 7 8 9
3 10 11 12
5 16 17 18
6 19 20 21
(我需要以不同的顺序对不同的子集执行此操作。这只是一个示例。)
我的尝试,
我的子集,
idx = [2,3,4,5]
idx2 = np.array(idx)
新订单
i = [2,0,1,3]
如果我这样做,
df.iloc[idx].reindex(idx2[i])
我确实以正确的顺序得到了子集,然后,我认为以下应该可行,
df.iloc[idx] = df.iloc[idx].reindex(idx2[i]).reset_index(drop=True)
但事实并非如此,因为它们需要在两边匹配索引。所以,我需要在索引上设置一个偏移量,这有点讨厌。或者进行此操作以忽略右侧的索引。
有什么想法吗?
您可以使用基于输入列表重新排列索引,然后在将重新排列的索引从原始索引中过滤出后将索引分成两组,然后使用 np.r_
和 df.iloc[]
来实现输出:
import more_itertools as mit
i = [2,0,1,3] #input list
rearranged_idx = df.index[2:6][i] #since you're interested in rows 2 to 5
i = [list(i) for i in
mit.consecutive_groups(df.index.difference(rearranged_idx,sort=False))]
# [[0, 1], [6]]
out = df.iloc[np.r_[i[0],rearranged_idx,i[-1]]]
a b c
0 1 2 3
1 4 5 6
4 13 14 15
2 7 8 9
3 10 11 12
5 16 17 18
6 19 20 21
因为pandas索引是不可变的,你可以把它做成一个数组,修改你想要的数组部分和reindex
:
idx = [2,3,4,5]
i = [2,0,1,3]
# pandas index to array
arr_idx = df.index.to_numpy()
# modify the order of the array
arr_idx[idx] = arr_idx[idx][i]
# reindex
df = df.reindex(arr_idx)
print (df)
a b c
0 1 2 3
1 4 5 6
4 7 8 9
2 10 11 12
3 13 14 15
5 16 17 18
6 19 20 21
使用
import pandas as pd
import numpy as np
鉴于此数据框,
df = pd.DataFrame(np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12],
[13, 14, 15],
[16, 17, 18],
[19, 20, 21]
]),
columns=['a', 'b', 'c'])
Out[1]:
a b c
0 1 2 3
1 4 5 6
2 7 8 9
3 10 11 12
4 13 14 15
5 16 17 18
6 19 20 21
我想重新排序并将第 2 到 5 行放回原位,
2 7 8 9
3 10 11 12
4 13 14 15
5 16 17 18
如果子集内的顺序是 [2,0,1,3]
,则期望的结果是,
Out[2]:
a b c
0 1 2 3
1 4 5 6
4 13 14 15
2 7 8 9
3 10 11 12
5 16 17 18
6 19 20 21
(我需要以不同的顺序对不同的子集执行此操作。这只是一个示例。)
我的尝试,
我的子集,
idx = [2,3,4,5]
idx2 = np.array(idx)
新订单
i = [2,0,1,3]
如果我这样做,
df.iloc[idx].reindex(idx2[i])
我确实以正确的顺序得到了子集,然后,我认为以下应该可行,
df.iloc[idx] = df.iloc[idx].reindex(idx2[i]).reset_index(drop=True)
但事实并非如此,因为它们需要在两边匹配索引。所以,我需要在索引上设置一个偏移量,这有点讨厌。或者进行此操作以忽略右侧的索引。 有什么想法吗?
您可以使用基于输入列表重新排列索引,然后在将重新排列的索引从原始索引中过滤出后将索引分成两组,然后使用 np.r_
和 df.iloc[]
来实现输出:
import more_itertools as mit
i = [2,0,1,3] #input list
rearranged_idx = df.index[2:6][i] #since you're interested in rows 2 to 5
i = [list(i) for i in
mit.consecutive_groups(df.index.difference(rearranged_idx,sort=False))]
# [[0, 1], [6]]
out = df.iloc[np.r_[i[0],rearranged_idx,i[-1]]]
a b c
0 1 2 3
1 4 5 6
4 13 14 15
2 7 8 9
3 10 11 12
5 16 17 18
6 19 20 21
因为pandas索引是不可变的,你可以把它做成一个数组,修改你想要的数组部分和reindex
:
idx = [2,3,4,5]
i = [2,0,1,3]
# pandas index to array
arr_idx = df.index.to_numpy()
# modify the order of the array
arr_idx[idx] = arr_idx[idx][i]
# reindex
df = df.reindex(arr_idx)
print (df)
a b c
0 1 2 3
1 4 5 6
4 7 8 9
2 10 11 12
3 13 14 15
5 16 17 18
6 19 20 21