在熊猫中按名称将列移到表的前面

这是我的 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()按索引移动列,但我想按名称移动列。

166920 次浏览

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

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.loc[:, 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

你可以使用早期版本的熊猫,也可以使用 ix来达到同样的效果:

df = df.ix[:, cols]

但是 ix从大熊猫 0.20.0开始就不被认可,而是 从熊猫1.0开始就停产了

可以在 Pandas 中使用 df.reindex ()函数。 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

定义列名列表

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

我不喜欢在其他解决方案中显式指定所有其他列的方式。

cfg_col_sel = ['Mid', 'Zscore']
cfg_col_sel = cfg_col_sel+[s for s in df.columns if not s in cfg_col_sel]
df = df[cfg_col_sel]

这是另一种做法,但不那么灵活

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]

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

前列:

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 ] ]

要对 DataFrame 的行进行重新排序,只需使用如下列表。

df = df[['Mid', 'Net', 'Upper', 'Lower', 'Zsore']]

这使得以后阅读代码时做了什么变得非常明显。还可以使用:

df.columns
Out[1]: Index(['Net', 'Upper', 'Lower', 'Mid', 'Zsore'], dtype='object')

然后剪切粘贴重新排序。


对于包含许多列的 DataFrame,将列列表存储在一个变量中,并将所需的列弹出到列表的前面。这里有一个例子:

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)

表现评估:

对于这个测试,当前的最后一列在每次重复中移到前面。就地方法通常执行得更好。然而,基于 .loc的 Ed Chum 方法和基于 reindex的 Sachinnm 方法是不可能的。

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

原始系统(2019) : 2015年年中 MacBook Pro 上的 Python 3.6.8和熊猫0.24.2。
当前系统(2022) : Python 3.10.5和 MacBook Pro 上的熊猫1.4.3(2021,Apple M1)。

import numpy as np
import pandas as pd


n_cols = 11
df = pd.DataFrame(np.random.randn(200000, n_cols),
columns=range(n_cols))


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


def move_to_front_normanius_inplace(df, col):
move_column_inplace(df, col, 0)
return df


def move_to_front_chum(df, col):
cols = list(df)
cols.insert(0, cols.pop(cols.index(col)))
return df.loc[:, cols]


def move_to_front_chum_inplace(df, col):
col = df[col]
df.drop(col.name, axis=1, inplace=True)
df.insert(0, col.name, col)
return df


def move_to_front_elpastor(df, col):
cols = [col] + [ c for c in df.columns if c!=col ]
return df[cols] # or df.loc[cols]


def move_to_front_sachinmm(df, col):
cols = df.columns.tolist()
cols.insert(0, cols.pop(cols.index(col)))
df = df.reindex(columns=cols, copy=False)
return df


def move_to_front_citynorman_inplace(df, col):
# This approach exploits that reset_index() moves the index
# at the first position of the data frame.
df.set_index(col, inplace=True)
df.reset_index(inplace=True)
return df


def test(method, df):
col = np.random.randint(0, n_cols)
method(df, col)


col = np.random.randint(0, n_cols)
ret_mine = move_to_front_normanius_inplace(df.copy(), col)
ret_chum1 = move_to_front_chum(df.copy(), col)
ret_chum2 = move_to_front_chum_inplace(df.copy(), col)
ret_elpas = move_to_front_elpastor(df.copy(), col)
ret_sach = move_to_front_sachinmm(df.copy(), col)
ret_city = move_to_front_citynorman_inplace(df.copy(), col)


# Assert equivalence of solutions.
assert(ret_mine.equals(ret_chum1))
assert(ret_mine.equals(ret_chum2))
assert(ret_mine.equals(ret_elpas))
assert(ret_mine.equals(ret_sach))
assert(ret_mine.equals(ret_city))

结果 :

# For n_cols = 11:
%timeit test(move_to_front_normanius_inplace, df)
# 137 µs ± 692 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 177 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 821 µs ± 11.8 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_chum, df)
# 926 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_elpastor, df)
# 901 µs ± 6.44 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 3.25 ms ± 32.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)




# For n_cols = 31:
%timeit test(move_to_front_normanius_inplace, df)
# 188 µs ± 3.46 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 214 µs ± 649 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 5.17 ms ± 68.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum, df)
# 5.52 ms ± 82.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_elpastor, df)
# 5.48 ms ± 198 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 14.7 ms ± 317 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

上面是2022年重新运行的更新值。在过去的几年中,不同系统的排名保持稳定,尽管绝对数量因为城市规范解和我的解(normanius)受益最大的因素在2到10之间有所减少。

这里有一个非常简单的答案。

不要忘记列名前后的两个(())‘方括号’。否则,它会给您一个错误。


# 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.set_index('Mid').reset_index()

看起来是个很简单的方法。

如果你想搬到另一个地方,并重新分配名称,你可以这样做:

df.insert(0, 'new col name', col)
df.pop("Mid")

Https://pandas.pydata.org/docs/reference/api/pandas

如果您想使用 将一列移动到数据流的前面e,可以使用 使用 set_index()

df.set_index(df.pop('column_name'), inplace=True)
df.reset_index(inplace=True)

你首先需要设置你想要放到前面的列作为数据帧的索引(我们做了一个 pop,以便在设置它作为索引之前从原始数据帧中删除列,以避免在下一个操作中名称冲突) ,最后调用 reset_index()使旧的索引成为数据帧的第一列。


有关详细信息,请参阅 如何更改大熊猫中数据框列的顺序

您可以使用 Python 中的 move column 包来移动列:

pip install movecolumn

然后你可以把你的代码写成:

import movecolumn as mc
mc.MoveTo1(df,'mid')

希望能帮上忙。

附注: 包裹可以在这里找到

简单快捷的解决办法:

熊猫 > = 1.3(2022年编辑) :

df.insert(0, 'mean', df.pop('mean'))

那么(对于熊猫 < 1.3,原始答案)呢

df.insert(0, 'mean', df['mean'])