Pandas에서 이름별로 열을 테이블 앞으로 이동


103

내 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()하지만 이름으로 이동하고 싶습니다.

답변:


121

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

를 사용 loc하여 ix향후 pandas 버전에서 더 이상 사용되지 않을 것과 동일한 결과를 얻을 수도 있습니다 0.20.0.

df = df.loc[:, cols]

에 대한 정보가 .loc대신 상단 에 표시 되어야합니다..ix
Gonçalo Peres 龚燿禄

57

아마도 내가 뭔가를 놓치고 있을지도 모르지만, 이러한 답변 중 상당수는 지나치게 복잡해 보입니다. 단일 목록 내에서 열을 설정할 수 있어야합니다.

기둥 앞쪽 :

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

다른 사람의 경우, 여러 열 3. 옵션 1이 삭제되지 않습니다 옵션을 사용하는 여러 열에 대한 확인 MidZscore원래의 위치에서 열에서. 나는 이것을 발견 Grouper오류가 동일한 열 두 번있을 때 GROUPBY하려고합니다.
the775

46

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

37

이 솔루션을 선호합니다.

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]하지 못했기 때문에 다른 제안을 포함하지 않았습니다.

MacBook Pro (Mid 2015)에서 python 3.6.8 및 pandas 0.24.2로 테스트했습니다.

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)
# 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)

2
훌륭한 솔루션. 그러나 열이 삽입 된 수정 된 df를 원래 df에 명시 적으로 할당해서는 안됩니다. 그래서 대신에 df = df.insert(0, col.name, col)우리는해야합니다 df.insert(0, col.name, col). move_column_inplace()그래도 기능에 올바르게 있습니다.
melihozbek

1
감사합니다 @normanius. 덱스터의 실험실에서 열심히 일 했어. :-) 훌륭한 솔루션. Occam의 면도기. 간단하고 우아합니다.
brohjoe

또한이 솔루션 : 선호
user88484

19

다른 솔루션에서 다른 모든 열을 명시 적으로 지정해야하는 방식이 마음에 들지 않았으므로 이것이 저에게 가장 적합했습니다. 대용량 데이터 프레임에서는 느릴 수 있지만 ...?

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


이것은 현재 버전의 reset_index()첫 번째 위치에 삭제 된 인덱스를 삽입하는 것을 악용합니다 . 그러나이 동작은 문서에 지정되어 있지 않습니다 .
normanius

1
공연은 내 대답을 참조하십시오. 및 inplace=True모두 에 사용 하는 것이 유리합니다 . set_index()reset_index()
normanius

9

다음은 열 위치를 다시 정렬하는 데 자주 사용하는 일반적인 코드 집합입니다. 유용 할 수 있습니다.

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

3
이상적으로는 귀하의 답변과 그것이 좋은 솔루션이되는 이유를 설명하고 코드를 게시하는 것이 아닙니다. 당신은 반대 투표를 할 위험이 있습니다
tjebo

5

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)

1001 개의 열로 구성된 DataFrame으로 작업하면 어떻게됩니까?
normanius

개념은 동일하지만 열이 많으면 열을 목록에 저장하고 목록을 조작해야합니다. 예제는 위의 편집 내용을 참조하십시오. 내 예는 실제로 stackoverflow.com/a/51009742/5827921 과 동일합니다 .
Dustin Helliwell

1

여기에 대한 아주 간단한 대답이 있습니다.

열 이름 주위에 두 개의 (()) '대괄호'를 잊지 마세요. 그렇지 않으면 오류가 발생합니다.


# 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

분명히 OP는 열 이름을 명시 적으로 철자를 원하지 않습니다. 매우 넓은 데이터 프레임의 경우에는 불가능할 수도 있습니다.
Ledger Yu

0

시도 할 수있는 가장 간단한 방법은 다음과 같습니다.

df=df[[ 'Mid',   'Upper',   'Lower', 'Net'  , 'Zsore']]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.