Pindahkan kolom menurut nama ke depan tabel di panda

97

Ini df saya:

                             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

Bagaimana cara memindahkan kolom dengan nama ( "Mid") ke depan tabel, indeks 0. Hasilnya akan terlihat seperti ini:

                             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

Kode saya saat ini memindahkan kolom dengan menggunakan indeks df.columns.tolist()tetapi saya ingin menggantinya dengan nama.

Boosted_d16
sumber

Jawaban:

114

Kita dapat menggunakan ixuntuk menyusun ulang dengan melewatkan daftar:

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

Metode lain adalah dengan mengambil referensi ke kolom dan memasukkannya kembali di depan:

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

Anda juga dapat menggunakan locuntuk mendapatkan hasil yang sama seperti yang ixakan dihentikan di versi panda yang akan datang mulai dari 0.20.0dan seterusnya:

df = df.loc[:, cols]
EdChum
sumber
54

Mungkin saya melewatkan sesuatu, tetapi banyak dari jawaban ini tampak terlalu rumit. Anda harus dapat mengatur kolom dalam satu daftar:

Kolom ke depan:

df = df[ ['Mid'] + [ col for col in df.columns if col != 'Mid' ] ]

Atau jika sebaliknya, Anda ingin memindahkannya ke belakang:

df = df[ [ col for col in df.columns if col != 'Mid' ] + ['Mid'] ]

Atau jika Anda ingin memindahkan lebih dari satu kolom:

cols_to_move = ['Mid', 'Zsore']
df           = df[ cols_to_move + [ col for col in df.columns if col not in cols_to_move ] ]
elPastor
sumber
Untuk orang lain, pastikan untuk beberapa kolom Anda menggunakan opsi 3. Opsi 1 dengan beberapa kolom tidak akan menghapus Mid& Zscoredari kolom dari posisi semula. Saya menemukan ini dengan Grouperkesalahan saat mencoba mengelompokkan ketika kolom yang sama ada dua kali.
the775
46

Anda dapat menggunakan fungsi df.reindex () di pandas. df adalah

                      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

tentukan daftar nama kolom

cols = df.columns.tolist()
cols
Out[13]: ['Net', 'Upper', 'Lower', 'Mid', 'Zsore']

pindahkan nama kolom ke mana pun Anda inginkan

cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[16]: ['Mid', 'Net', 'Upper', 'Lower', 'Zsore']

kemudian gunakan df.reindex()fungsi untuk menyusun ulang

df = df.reindex(columns= cols)

out put adalah: 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
Sachinmm
sumber
31

Saya lebih suka solusi ini:

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

Ini lebih mudah dibaca dan lebih cepat daripada jawaban yang disarankan lainnya.

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

Penilaian kinerja:

Untuk pengujian ini, kolom terakhir saat ini dipindahkan ke depan di setiap pengulangan. Metode di tempat biasanya bekerja lebih baik. Sementara solusi citynorman dapat dibuat di tempat, metode Ed Chum berdasarkan .locdan metode sachinnm berdasarkan reindextidak bisa.

Sementara metode lain bersifat umum, solusi citynorman terbatas pada pos=0. Saya tidak mengamati perbedaan kinerja apa pun antara df.loc[cols]dan df[cols], itulah sebabnya saya tidak menyertakan beberapa saran lain.

Saya menguji dengan python 3.6.8 dan pandas 0.24.2 di MacBook Pro (Pertengahan 2015).

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

Hasil :

# 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)
normanius
sumber
2
Solusi bagus. Namun, kita tidak boleh menetapkan df yang dimodifikasi dengan kolom yang disisipkan ke df asli secara eksplisit. Jadi, alih-alih df = df.insert(0, col.name, col), kita perlu melakukannya df.insert(0, col.name, col). Anda memilikinya dengan benar dalam fungsinya move_column_inplace().
melihozbek
1
Terima kasih @normanius. Sudah bekerja keras di Laboratorium Dexter, begitu. :-) Solusi yang bagus. Pisau cukur Occam. Sederhana dan elegan.
brohjoe
Saya juga lebih suka solusi ini :)
user88484
19

Saya tidak suka bagaimana saya harus secara eksplisit menentukan semua kolom lain di solusi lain jadi ini bekerja paling baik untuk saya. Meskipun mungkin lambat untuk kerangka data besar ...?

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

citynorman.dll
sumber
Ini mengeksploitasi bahwa versi saat ini dari reset_index()memasukkan indeks yang dijatuhkan di posisi pertama. Namun, perhatikan bahwa perilaku ini tidak ditentukan di dokumen .
normanius
1
Adapun performanya, lihat jawaban saya. Ini menguntungkan digunakan inplace=Trueuntuk set_index()dan reset_index().
normanius
9

Berikut ini sekumpulan kode umum yang sering saya gunakan untuk mengatur ulang posisi kolom. Anda mungkin merasa berguna.

cols = df.columns.tolist()
n = int(cols.index('Mid'))
cols = [cols[n]] + cols[:n] + cols[n+1:]
df = df[cols]
Bhagabat Behera
sumber
3
idealnya, jelaskan jawaban Anda dan apa yang menjadikannya sebagai solusi yang baik, dan tidak hanya mengeposkan sepotong kode. Anda mempertaruhkan downvoting
Tjebo
5

Untuk menyusun ulang baris DataFrame cukup gunakan daftar sebagai berikut.

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

Ini membuatnya sangat jelas apa yang dilakukan saat membaca kode nanti. Juga gunakan:

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

Kemudian potong dan tempel untuk menyusun ulang.


Untuk DataFrame dengan banyak kolom, simpan daftar kolom dalam variabel dan pop kolom yang diinginkan ke depan daftar. Berikut ini contohnya:

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]

Sekarang df.columnspunya.

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)
Dustin Helliwell
sumber
Bagaimana jika Anda bekerja dengan DataFrame yang terdiri dari 1001 kolom?
normanius
Konsepnya sama, namun dengan banyak kolom, kolom harus disimpan dalam daftar dan daftar harus dimanipulasi. Lihat suntingan saya di atas sebagai contoh. Contoh saya secara efektif sama dengan stackoverflow.com/a/51009742/5827921 .
Dustin Helliwell
1

Inilah jawaban yang sangat sederhana untuk ini.

Jangan lupa dua (()) 'tanda kurung' di sekitar nama kolom. Jika tidak, itu akan memberi Anda kesalahan.


# 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
rra
sumber
jelas OP tidak ingin secara eksplisit mengeja nama kolom. Dalam beberapa kasus dengan dataframe yang sangat lebar bahkan mungkin tidak dapat dilakukan.
Ledger Yu
0

Hal paling sederhana yang dapat Anda coba adalah:

df=df[[ 'Mid',   'Upper',   'Lower', 'Net'  , 'Zsore']]
NeelMani Shrivastava
sumber