Python 按名称将列移动到表中的前面

Python 按名称将列移动到表中的前面,python,pandas,move,dataframe,shift,Python,Pandas,Move,Dataframe,Shift,这是我的df: Net Upper Lower Mid Zsore Answer option More than once a day 0% 0.22% -0.12% 2 65 Once a day 0% 0.32% -0.19% 3 45

这是我的df:

                             Net   Upper   Lower  Mid  Zsore
Answer option                                                
More than once a day          0%   0.22%  -0.12%   2    65 
Once a day                    0%   0.32%  -0.19%   3    45
Several times a week          2%   2.45%   1.10%   4    78
Once a week                   1%   1.63%  -0.40%   6    65
如何按名称(
“Mid”
)将列移动到表的前面,索引为0。结果应该是这样的:

                             Mid   Upper   Lower  Net  Zsore
Answer option                                                
More than once a day          2   0.22%  -0.12%   0%    65 
Once a day                    3   0.32%  -0.19%   0%    45
Several times a week          4   2.45%   1.10%   2%    78
Once a week                   6   1.63%  -0.40%   1%    65

我当前的代码使用
df.columns.tolist()
按索引移动列,但我想按名称移动它

我们可以使用
ix
通过传递列表来重新排序:

In [27]:
# get a list of columns
cols = list(df)
# move the column to head of list using index, pop and insert
cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[27]:
['Mid', 'Net', 'Upper', 'Lower', 'Zsore']
In [28]:
# use ix to reorder
df = df.ix[:, cols]
df
Out[28]:
                      Mid Net  Upper   Lower  Zsore
Answer_option                                      
More_than_once_a_day    2  0%  0.22%  -0.12%     65
Once_a_day              3  0%  0.32%  -0.19%     45
Several_times_a_week    4  2%  2.45%   1.10%     78
Once_a_week             6  1%  1.63%  -0.40%     65
另一种方法是引用列并在前面重新插入:

In [39]:
mid = df['Mid']
df.drop(labels=['Mid'], axis=1,inplace = True)
df.insert(0, 'Mid', mid)
df
Out[39]:
                      Mid Net  Upper   Lower  Zsore
Answer_option                                      
More_than_once_a_day    2  0%  0.22%  -0.12%     65
Once_a_day              3  0%  0.32%  -0.19%     45
Several_times_a_week    4  2%  2.45%   1.10%     78
Once_a_week             6  1%  1.63%  -0.40%     65
df = df[ ['Mid'] + [ col for col in df.columns if col != 'Mid' ] ]
您还可以使用
loc
获得与将来版本的pandas中不再推荐使用
ix
相同的结果:

您可以在pandas中使用df.reindex()函数。 df是

定义列名列表

cols = df.columns.tolist()
cols
Out[13]: ['Net', 'Upper', 'Lower', 'Mid', 'Zsore']
将列名移动到所需的任何位置

cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[16]: ['Mid', 'Net', 'Upper', 'Lower', 'Zsore']
然后使用
df.reindex()
函数重新排序

df = df.reindex(columns= cols)
输出为:df

                      Mid  Upper   Lower Net  Zsore
Answer option                                      
More than once a day    2  0.22%  -0.12%  0%     65
Once a day              3  0.32%  -0.19%  0%     45
Several times a week    4  2.45%   1.10%  2%     78
Once a week             6  1.63%  -0.40%  1%     65

我不喜欢我必须明确指定其他解决方案中所有其他列的方式,因此这对我来说是最好的。虽然对于大型数据帧来说可能会很慢


df=df.set_index('Mid').reset_index()

这是一组我经常用来重新排列列位置的通用代码。你会发现它很有用

cols = df.columns.tolist()
n = int(cols.index('Mid'))
cols = [cols[n]] + cols[:n] + cols[n+1:]
df = df[cols]

也许我遗漏了什么,但这些答案中有很多似乎过于复杂。您应该能够在单个列表中设置列:

前面的立柱:

In [39]:
mid = df['Mid']
df.drop(labels=['Mid'], axis=1,inplace = True)
df.insert(0, 'Mid', mid)
df
Out[39]:
                      Mid Net  Upper   Lower  Zsore
Answer_option                                      
More_than_once_a_day    2  0%  0.22%  -0.12%     65
Once_a_day              3  0%  0.32%  -0.19%     45
Several_times_a_week    4  2%  2.45%   1.10%     78
Once_a_week             6  1%  1.63%  -0.40%     65
df = df[ ['Mid'] + [ col for col in df.columns if col != 'Mid' ] ]
或者,如果要将其移到后面:

df = df[ [ col for col in df.columns if col != 'Mid' ] + ['Mid'] ]
或者,如果要移动多个列:

cols_to_move = ['Mid', 'Zsore']
df           = df[ cols_to_move + [ col for col in df.columns if col not in cols_to_move ] ]

要对数据帧的行重新排序,只需使用如下列表

df = df[['Mid', 'Net', 'Upper', 'Lower', 'Zsore']]
这使得以后阅读代码时所做的事情变得非常明显。也可使用:

df.columns
Out[1]: Index(['Net', 'Upper', 'Lower', 'Mid', 'Zsore'], dtype='object')
然后剪切并粘贴以重新排序


对于具有许多列的数据帧,将列列表存储在变量中,并将所需列弹出到列表的前面。以下是一个例子:

cols = [str(col_name) for col_name in range(1001)]
data = np.random.rand(10,1001)
df = pd.DataFrame(data=data, columns=cols)

mv_col = cols.pop(cols.index('77'))
df = df[[mv_col] + cols]
现在,
df.columns

Index(['77', '0', '1', '2', '3', '4', '5', '6', '7', '8',
       ...
       '991', '992', '993', '994', '995', '996', '997', '998', '999', '1000'],
      dtype='object', length=1001)

我更喜欢这个解决方案:

col = df.pop("Mid")
df.insert(0, col.name, col)
它比其他建议的答案更简单,速度更快

def move_column_inplace(df, col, pos):
    col = df.pop(col)
    df.insert(pos, col.name, col)

绩效评估:

对于此测试,在每次重复中,当前最后一列将移到前面。就地方法通常表现更好。虽然citynorman的解决方案可以到位,但Ed Chum基于
.loc
的方法和sachinnm基于
reindex
的方法无法到位

虽然其他方法是通用的,但citynorman的解决方案仅限于
pos=0
。我没有观察到
df.loc[cols]
df[cols]
之间有任何性能差异,这就是为什么我没有包括一些其他建议的原因

我在MacBookPro上测试了python 3.6.8和pandas 0.24.2(2015年年中)

结果

# For n_cols = 11:
%timeit test(move_to_front_normanius_inplace, df)
# 1.05 ms ± 42.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 1.68 ms ± 46.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 3.24 ms ± 96.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum, df)
# 3.84 ms ± 114 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_elpastor, df)
# 3.85 ms ± 58.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 9.67 ms ± 101 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


# For n_cols = 31:
%timeit test(move_to_front_normanius_inplace, df)
# 1.26 ms ± 31.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 1.95 ms ± 260 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_sachinmm, df)
# 10.7 ms ± 348 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum, df)
# 11.5 ms ± 869 µs per loop (mean ± std. dev. of 7 runs, 100 loops each
%timeit test(move_to_front_elpastor, df)
# 11.4 ms ± 598 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 31.4 ms ± 1.89 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
这里有一个非常简单的答案。 不要忘记列名称周围的两个(())括号。否则,它会给您一个错误


# here you can add below line and it should work 
df = df[list(('Mid','Upper', 'Lower', 'Net','Zsore'))]
df

                             Mid   Upper   Lower  Net  Zsore
Answer option                                                
More than once a day          2   0.22%  -0.12%   0%    65 
Once a day                    3   0.32%  -0.19%   0%    45
Several times a week          4   2.45%   1.10%   2%    78
Once a week                   6   1.63%  -0.40%   1%    65

您可以尝试的最简单的方法是:

df=df[[ 'Mid',   'Upper',   'Lower', 'Net'  , 'Zsore']]
df.设置索引('Mid')。重置索引()

这似乎是一个非常简单的方法。

理想情况下,解释你的答案以及是什么使它成为一个好的解决方案,而不仅仅是发布一段代码。如果您使用由1001列组成的数据帧,则会有下降的风险。概念是相同的,但是对于许多列,这些列应该存储在列表中,并且应该对列表进行操作。有关示例,请参见上面的“我的编辑”。我的示例实际上与相同。这利用了当前版本的
reset\u index()
在第一个位置插入删除的索引。但是,请注意,中没有指定此行为。至于性能,请参阅我的答案。对于
set_index()
reset_index()
,使用
inplace=True
都很有利。这是一个很好的解决方案。但是,我们不应该将带有插入列的修改后的df显式地分配给原始df。因此,我们需要做的不是
df=df.insert(0,col.name,col)
,而是
df.insert(0,col.name,col)
。不过,在函数
move\u column\u inplace()
中,它是正确的。谢谢@normanius。在德克斯特的实验室里努力工作,我明白了。:-)很好的解决方案。奥卡姆剃刀。简单而优雅。我也更喜欢这种解决方案:)对于其他人,请确保使用选项3的多个列。具有多个列的选项1不会从原始位置从列中删除
Mid
&
Zscore
。当同一列出现两次时,我在尝试分组时发现了一个
Grouper
错误。显然OP不想显式地拼写出列名。在某些情况下,对于非常宽的数据帧,甚至可能不可能这样做。
.loc
上的信息应该位于顶部,而不是
.ix
df=df[[ 'Mid',   'Upper',   'Lower', 'Net'  , 'Zsore']]