将给定行移动到DataFrame的末尾

9
我希望能够从DataFrame中取出一行数据,并将其添加到DataFrame的开头或结尾。
下面是我的代码,它可以实现这个功能,但我不确定是否使用了正确的方法,或者是否有更简单、更好、更快的方法?
testdf = df.copy()
#get row 
target_row = testdf.ix[[2],:]
#del row from df
testdf.drop([testdf.index[2]], axis=0, inplace=True)
#concat original row to end or start of df
newdf = pd.concat([testdf, target_row], axis=0)

谢谢

6个回答

10
与其使用 concat,我更倾向于在 shift 后直接将值分配给 df,然后使用 iloc 引用要分配行的位置。你必须调用 squeeze,以便仅分配值并且丢失原始索引值,否则它会引发一个 ValueError
In [210]:
df = pd.DataFrame({'a':np.arange(5)})
df

Out[210]:
   a
0  0
1  1
2  2
3  3
4  4

In [206]:
target_row = df.ix[[2],:]
target_row

Out[206]:
   a
2  2

In [211]:
df = df.shift()
df.iloc[0] = target_row.squeeze()
df

Out[211]:
   a
0  2
1  0
2  1
3  2
4  3

编辑

在末尾插入:

In [255]:
df = pd.DataFrame({'a':np.arange(5)})
target_row = df.ix[[2],:]
df = df.shift(-1)
df.iloc[-1] = target_row.squeeze()
df

Out[255]:
   a
0  1
1  2
2  3
3  4
4  2

另一个更新

感谢@AsheKetchum指出我的早期答案是错误的,现在我看着这个问题三年后,我意识到你可以只需重新索引原始数据框:

如果我们将索引的副本作为list

In[24]:
idx = df.index.tolist()
idx

Out[24]: [0, 1, 2, 3, 4]

然后,我们可以从此列表中pop出所需的索引:
In[25]:
idx.pop(2)
idx

Out[25]: [0, 1, 3, 4]

现在我们可以通过在此列表前面添加内容来重新索引:
In[26]:
df.reindex([2] + idx)

Out[26]: 
   a
2  2
0  0
1  1
3  3
4  4

或者追加:

In[27]:    
df.reindex(idx+[2])

Out[27]: 
   a
0  0
1  1
3  3
4  4
2  2

这样对吗?在你编辑之前的例子中,你让列a中的4消失了。这是期望的输出吗? - AsheKetchum
1
@AsheKetchum 很好的观点,再次查看这个问题和 OP 所做的事情,我的答案是不正确的,我会更新。 - EdChum
请注意,.ix已被弃用,请使用.iloc代替。 - raummensch

4
为了提高性能,您可能需要考虑保留一个正在运行的列表,其中包含您想要移动到DataFrame末尾的所有行,然后在单个pd.concat操作中一次性将它们全部移动。
df = pd.DataFrame(np.random.rand(5, 3), columns=list('ABC'))
target_rows = [1, 3, 4]

a = df.iloc[[i for i in df.index if i not in target_rows], :]
b = df.iloc[target_rows, :]
>>> pd.concat([a, b])
          A         B         C
0  0.818722  0.174153  0.522383
2  0.581577  0.840306  0.985089
1  0.645752  0.238476  0.670922
3  0.198271  0.501911  0.954477
4  0.965488  0.735559  0.701077

3
我可以将其简化为一行代码:
pd.concat([df.ix[0:1], df.ix[3:], df.ix[[2]]])

虽然我没有看到你的代码和我的代码之间有任何性能差异,但很可能是拷贝造成了这种情况。


0

与YH Wu所写的类似,如果您知道索引(或索引),则可以在一行中完成它。但是,ix已被弃用,请改用loc:

import pandas as pd
import numpy as np

df = pd.DataFrame({'a':np.arange(5)})

#    a
# 0  0
# 1  1
# 2  2
# 3  3
# 4  4

# move the line with index 2 to the end:
df2 = df.drop(2).append(df.loc[2])

#    a
# 0  0
# 1  1
# 3  3
# 4  4
# 2  2

# several indices, moves 3 and 2 to the end in that order:
to_move = [3, 2]
df2 = df.drop(to_move).append(df.loc[to_move])

#    a
# 0  0
# 1  1
# 4  4
# 3  3
# 2  2

.drop会删除你作为参数给出的索引所在的行。使用df.loc[x]可以选择具有索引x的行。如果你写了df = df.drop...,那么你直接将更改应用到原始DataFrame中。如果你想重置索引,可以使用“.reset_index(drop=True)”(如果你不想将原始索引保留为新列,则设置drop=True)。


0
如果您需要按值移动行(例如,您知道索引的名称,但不知道其位置),则可以使用以下方法(假设索引的值为2):
df.reindex([index for index in df.index if index != 2] + [2], axis=0)

逻辑如下:

1. [index for index in df.index if index != 2] # create a list of all indexes except for the one you want to move to the end
2. + [2] # append the index you want to move to the end
3. reindex across the index (axis=0)

这种方法的优点:

  1. 可以与您想要移动的任意数量的索引一起使用
  2. 可以轻松修改以将所需索引移动到前面而不是后面
  3. 没有硬编码:我们按值移动索引,而不是按其位置
  4. 列表推导提供良好的性能

-1

我只需删除一行或多行,然后在末尾添加。

df = pd.DataFrame({'a':np.arange(5)})
df.drop(2).append(df.ix[2]).reset_index(drop=True) # move 3rd row
df.drop(df.head(2).index).append(df.head(2)).reset_index() # move first 2 rows

你可能想要添加一些评论来解释你的答案。 - Fabian Fagerholm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接