Memilih beberapa kolom dalam bingkai data panda

1113

Saya memiliki data dalam kolom yang berbeda tetapi saya tidak tahu cara mengekstraknya untuk menyimpannya dalam variabel lain.

index  a   b   c
1      2   3   4
2      3   4   5

Bagaimana saya memilih 'a', 'b'dan menyimpannya di df1?

Saya mencoba

df1 = df['a':'b']
df1 = df.ix[:, 'a':'b']

Sepertinya tidak ada yang berhasil.

pengguna1234440
sumber
2
Anda tidak pernah ingin menggunakan .ixkarena ambigu. Gunakan .ilocatau .locjika Anda harus.
Acumenus
1
Apakah ada cara yang bisa dilakukan tanpa merujuk pada nama header? seperti di R, saya bisa melakukannya seperti ini: > csvtable_imp_1 <- csvtable_imp[0:6]dan ia memilih jumlah delta kolom pertama antara 0 dan 6. Yang harus saya lakukan adalah membaca tabel csv sebagaimana dibatasi dengan lib readr.
MichaelR
Saya telah bekerja sedikit lebih banyak dengannya. Menemukan sesuatu yang berfungsi seperti yang diinginkan. Default adalah untuk memilih jumlah char dan bukan kolom. infile_1 = largefile_stay.ix[:,0:6]
MichaelR
3
Bagi mereka yang tersandung pada masalah ini, ixsekarang sudah usang. Panda merekomendasikan untuk menggunakan: loc(pengindeksan berbasis label) atau iloc(pengindeksan berbasis posisi).
ZaydH

Jawaban:

1771

Nama kolom (yang merupakan string) tidak dapat diiris dengan cara Anda mencoba.

Di sini Anda memiliki beberapa opsi. Jika Anda tahu dari konteks, variabel mana yang ingin Anda potong, Anda bisa mengembalikan tampilan hanya kolom-kolom tersebut dengan meneruskan daftar ke dalam __getitem__sintaks (tanda []).

df1 = df[['a','b']]

Atau, jika penting untuk mengindeksnya secara numerik dan bukan dengan nama mereka (katakan kode Anda secara otomatis harus melakukan ini tanpa mengetahui nama dua kolom pertama) maka Anda dapat melakukan ini sebagai gantinya:

df1 = df.iloc[:,0:2] # Remember that Python does not slice inclusive of the ending index.

Selain itu, Anda harus membiasakan diri dengan gagasan tampilan ke objek Pandas vs salinan objek itu. Yang pertama dari metode di atas akan mengembalikan salinan baru dalam memori sub-objek yang diinginkan (irisan yang diinginkan).

Namun, kadang-kadang ada konvensi pengindeksan dalam Panda yang tidak melakukan ini dan sebaliknya memberikan Anda variabel baru yang hanya merujuk pada potongan memori yang sama dengan sub-objek atau irisan pada objek asli. Ini akan terjadi dengan cara pengindeksan kedua, sehingga Anda dapat memodifikasinya dengan copy()fungsi untuk mendapatkan salinan biasa. Ketika ini terjadi, mengubah apa yang Anda pikirkan adalah objek yang diiris kadang-kadang dapat mengubah objek asli. Selalu bagus untuk waspada untuk ini.

df1 = df.iloc[0,0:2].copy() # To avoid the case where changing df1 also changes df

Untuk menggunakannya iloc, Anda perlu mengetahui posisi kolom (atau indeks). Karena posisi kolom dapat berubah, alih-alih indeks hard-coding, Anda dapat menggunakan ilocbersama get_locfungsi columnsmetode objek dataframe untuk mendapatkan indeks kolom.

{df.columns.get_loc(c):c for idx, c in enumerate(df.columns)}

Sekarang Anda dapat menggunakan kamus ini untuk mengakses kolom melalui nama dan menggunakan iloc.

Ely
sumber
192
Catatan: df[['a','b']]menghasilkan salinan
Wes McKinney
1
Ya ini tersirat dalam jawaban saya. Bit tentang salinan itu hanya untuk digunakan ix[]jika Anda lebih suka menggunakan ix[]untuk alasan apa pun.
Ely
1
ixindeks baris, bukan kolom. Saya pikir OP menginginkan kolom.
hobs
9
ixmenerima argumen slice, jadi Anda juga bisa mendapatkan kolom. Misalnya, df.ix[0:2, 0:2]dapatkan sub-array 2x2 kiri atas seperti halnya matriks NumPy (tergantung pada nama kolom Anda tentu saja). Anda bahkan dapat menggunakan sintaks slice pada nama string kolom, seperti df.ix[0, 'Col1':'Col5']. Itu mendapatkan semua kolom yang kebetulan dipesan antara Col1dan Col5dalam df.columnsarray. Tidak benar untuk mengatakan bahwa ixbaris indeks. Itu hanya penggunaannya yang paling dasar. Ini juga mendukung pengindeksan lebih dari itu. Jadi, ixsangat umum untuk pertanyaan ini.
ely
7
@AndrewCassidy Jangan pernah gunakan .ix lagi. Jika Anda ingin memotong dengan menggunakan bilangan bulat .ilocyang eksklusif dari posisi terakhir seperti daftar Python.
Ted Petrou
133

Pada versi 0.11.0, kolom dapat diiris dengan cara Anda mencoba menggunakan .locpengindeks:

df.loc[:, 'C':'E']

setara dengan

df[['C', 'D', 'E']]  # or df.loc[:, ['C', 'D', 'E']]

dan mengembalikan kolom Cmelalui E.


Demo pada DataFrame yang dibuat secara acak:

import pandas as pd
import numpy as np
np.random.seed(5)
df = pd.DataFrame(np.random.randint(100, size=(100, 6)), 
                  columns=list('ABCDEF'), 
                  index=['R{}'.format(i) for i in range(100)])
df.head()

Out: 
     A   B   C   D   E   F
R0  99  78  61  16  73   8
R1  62  27  30  80   7  76
R2  15  53  80  27  44  77
R3  75  65  47  30  84  86
R4  18   9  41  62   1  82

Untuk mendapatkan kolom dari C ke E (perhatikan bahwa tidak seperti slice integer, 'E' termasuk dalam kolom):

df.loc[:, 'C':'E']

Out: 
      C   D   E
R0   61  16  73
R1   30  80   7
R2   80  27  44
R3   47  30  84
R4   41  62   1
R5    5  58   0
...

Hal yang sama berlaku untuk memilih baris berdasarkan label. Dapatkan baris 'R6' hingga 'R10' dari kolom tersebut:

df.loc['R6':'R10', 'C':'E']

Out: 
      C   D   E
R6   51  27  31
R7   83  19  18
R8   11  67  65
R9   78  27  29
R10   7  16  94

.locjuga menerima array boolean sehingga Anda dapat memilih kolom yang sesuai entri dalam array True. Misalnya, df.columns.isin(list('BCD'))kembali array([False, True, True, True, False, False], dtype=bool)- Benar jika nama kolom ada di daftar ['B', 'C', 'D']; Salah, sebaliknya.

df.loc[:, df.columns.isin(list('BCD'))]

Out: 
      B   C   D
R0   78  61  16
R1   27  30  80
R2   53  80  27
R3   65  47  30
R4    9  41  62
R5   78   5  58
...
ayhan
sumber
110

Dengan asumsi nama kolom Anda ( df.columns) adalah ['index','a','b','c'], maka data yang Anda inginkan ada di kolom 3 & 4. Jika Anda tidak tahu nama mereka saat skrip Anda berjalan, Anda dapat melakukan ini

newdf = df[df.columns[2:4]] # Remember, Python is 0-offset! The "3rd" entry is at slot 2.

Seperti yang ditunjukkan oleh EMS dalam jawabannya , df.ixmengiris kolom sedikit lebih ringkas, tetapi .columnsantarmuka pengiris mungkin lebih alami karena menggunakan sintaksis daftar / pengindeksan daftar python vanilla 1-D.

PERINGATAN: 'index'adalah nama yang buruk untuk sebuah DataFramekolom. Label yang sama juga digunakan untuk df.indexatribut sebenarnya , sebuah Indexarray. Jadi kolom Anda dikembalikan oleh df['index']dan indeks DataFrame nyata dikembalikan oleh df.index. An Indexadalah jenis khusus yang Seriesdioptimalkan untuk pencarian nilai-nilai elemen itu. Untuk df.index itu untuk mencari baris dengan label mereka. Itu df.columnsatribut juga merupakan pd.Indexarray, untuk mencari kolom dengan label mereka.

hobs
sumber
3
Seperti yang saya sebutkan dalam komentar saya di atas, .ixadalah bukan hanya untuk baris. Ini untuk mengiris tujuan umum, dan dapat digunakan untuk mengiris multidimensi. Ini pada dasarnya hanya sebuah antarmuka untuk __getitem__sintaks NumPy yang biasa . Yang mengatakan, Anda dapat dengan mudah mengubah masalah mengiris kolom menjadi masalah mengiris baris dengan hanya menerapkan operasi transpos df.T,. Contoh Anda menggunakan columns[1:3], yang sedikit menyesatkan. Hasilnya columnsadalah a Series; hati-hati jangan hanya memperlakukannya seperti array. Juga, Anda mungkin harus mengubahnya columns[2:3]agar sesuai dengan komentar "3 & 4" Anda.
ely
@ Mr.F: Saya [2:4]benar. Anda [2:3]salah. Dan menggunakan notasi pengiris python standar untuk menghasilkan urutan / Seri tidak menyesatkan IMO. Tapi saya suka memotong antarmuka DataFrame Anda untuk mengakses array numpy yang mendasarinya ix.
Hobs
Anda benar dalam hal ini, tetapi poin yang saya coba utarakan adalah bahwa secara umum, mengiris label pada Panda termasuk titik akhir slice (atau setidaknya ini adalah perilaku di sebagian besar versi Panda sebelumnya). Jadi jika Anda mengambil df.columnsdan ingin mengirisnya dengan label , maka Anda akan memiliki semantik slice yang berbeda daripada jika Anda mengirisnya dengan posisi indeks integer . Saya jelas tidak menjelaskannya dengan baik di komentar saya sebelumnya.
Ely
Ahh, sekarang aku mengerti maksudmu. Saya lupa itu columnsadalah Seri yang tidak dapat diubah dan pengambil telah diganti untuk menggunakan label sebagai indeks. Terima kasih telah meluangkan waktu untuk mengklarifikasi.
Hobs
2
Perhatikan Peringatan Penghentian: .ix sudah ditinggalkan. Karenanya ini masuk akal: newdf = df [df.columns [2: 4]]
Martien Lubberink
64
In [39]: df
Out[39]: 
   index  a  b  c
0      1  2  3  4
1      2  3  4  5

In [40]: df1 = df[['b', 'c']]

In [41]: df1
Out[41]: 
   b  c
0  3  4
1  4  5
Wes McKinney
sumber
1
Bagaimana jika saya ingin mengubah nama kolom, misalnya sesuatu seperti: df[['b as foo', 'c as bar']sehingga output mengganti nama kolom bsebagai foodan kolom csebagai bar?
kuanb
5
df[['b', 'c']].rename(columns = {'b' : 'foo', 'c' : 'bar'})
Greg
62

Saya menyadari pertanyaan ini sudah cukup lama, tetapi dalam versi panda terbaru ada cara mudah untuk melakukan hal ini. Nama kolom (yang merupakan string) dapat diiris dengan cara apa pun yang Anda suka.

columns = ['b', 'c']
df1 = pd.DataFrame(df, columns=columns)
zerovektor
sumber
6
Ini hanya dapat dilakukan pada penciptaan. Pertanyaannya adalah menanyakan apakah Anda sudah memilikinya di dalam dataframe.
Banjocat
3
@ Banjocat, ia bekerja dengan kerangka data yang ada
mhery
23

Anda bisa memberikan daftar kolom yang akan dijatuhkan dan mengembalikan DataFrame hanya dengan kolom yang diperlukan menggunakan drop()fungsi pada Pandaf DataFrame.

Hanya mengatakan

colsToDrop = ['a']
df.drop(colsToDrop, axis=1)

akan mengembalikan DataFrame hanya dengan kolom bdan c.

The dropMetode ini didokumentasikan di sini .

Muthu Chithambara Jothi
sumber
23

Dengan panda,

dengan nama kolom

dataframe[['column1','column2']]

untuk memilih berdasarkan iloc dan kolom tertentu dengan nomor indeks:

dataframe.iloc[:,[1,2]]

dengan nama kolom loc dapat digunakan seperti

dataframe.loc[:,['column1','column2']]
Vivek Ananthan
sumber
20

Saya menemukan metode ini sangat berguna:

# iloc[row slicing, column slicing]
surveys_df.iloc [0:3, 1:4]

Rincian lebih lanjut dapat ditemukan di sini

Alvis
sumber
Bagaimana Anda akan mengambil, katakanlah, hanya kolom 2 dan 5?
324
1
Itu akan terjadi surveys_df.iloc [:, [2,5]].
Julian Gorfer
15

Dimulai dengan 0.21.0, menggunakan .locatau []dengan daftar dengan satu atau lebih label yang hilang sudah tidak digunakan lagi .reindex. Jadi, jawaban untuk pertanyaan Anda adalah:

df1 = df.reindex(columns=['b','c'])

Dalam versi sebelumnya, menggunakan .loc[list-of-labels]akan berfungsi selama setidaknya 1 kunci ditemukan (jika tidak maka akan meningkatkan a KeyError). Perilaku ini sudah usang dan sekarang menampilkan pesan peringatan. Alternatif yang direkomendasikan adalah menggunakan .reindex().

Baca lebih lanjut di Pengindeksan dan Memilih Data

tozCSS
sumber
10

Anda bisa menggunakan panda. Saya membuat DataFrame:

    import pandas as pd
    df = pd.DataFrame([[1, 2,5], [5,4, 5], [7,7, 8], [7,6,9]], 
                      index=['Jane', 'Peter','Alex','Ann'],
                      columns=['Test_1', 'Test_2', 'Test_3'])

DataFrame:

           Test_1  Test_2  Test_3
    Jane        1       2       5
    Peter       5       4       5
    Alex        7       7       8
    Ann         7       6       9

Untuk memilih 1 atau lebih kolom dengan nama:

    df[['Test_1','Test_3']]

           Test_1  Test_3
    Jane        1       5
    Peter       5       5
    Alex        7       8
    Ann         7       9

Anda juga bisa menggunakan:

    df.Test_2

Dan Anda mendapatkan kolom Test_2

    Jane     2
    Peter    4
    Alex     7
    Ann      6

Anda juga dapat memilih kolom dan baris dari baris ini menggunakan .loc(). Ini disebut "mengiris" . Perhatikan bahwa saya ambil dari kolom Test_1keTest_3

    df.loc[:,'Test_1':'Test_3']

"Slice" adalah:

            Test_1  Test_2  Test_3
     Jane        1       2       5
     Peter       5       4       5
     Alex        7       7       8
     Ann         7       6       9

Dan jika Anda hanya ingin Peterdan Anndari kolom Test_1dan Test_3:

    df.loc[['Peter', 'Ann'],['Test_1','Test_3']]

Anda mendapatkan:

           Test_1  Test_3
    Peter       5       5
    Ann         7       9
pink.slash
sumber
8

Jika Anda ingin mendapatkan satu elemen dengan indeks baris dan nama kolom, Anda dapat melakukannya seperti itu df['b'][0]. Ini sesederhana yang Anda bisa gambar.

Atau Anda dapat menggunakan df.ix[0,'b'], campuran penggunaan indeks dan label.

Catatan: Sejak v0.20 ixsudah tidak digunakan lagi karena loc/ iloc.

W.Perrin
sumber
6

Satu pendekatan yang berbeda dan mudah: iterasi baris

menggunakan iterows

 df1= pd.DataFrame() #creating an empty dataframe
 for index,i in df.iterrows():
    df1.loc[index,'A']=df.loc[index,'A']
    df1.loc[index,'B']=df.loc[index,'B']
    df1.head()
Ankita
sumber
5
Tolong jangan rekomendasikan penggunaan iterrows (). Ini adalah pendukung nyata dari pola anti terburuk dalam sejarah panda.
cs95
Bisakah Anda jelaskan apa yang Anda maksud dengan "pola terburuk"?
Ankita
1
IMHO, iterrows () harus menjadi opsi terakhir saat menggunakan panda.
Elf
5

Berbagai pendekatan yang dibahas dalam respons di atas didasarkan pada asumsi bahwa pengguna tahu indeks kolom untuk turun atau subset, atau pengguna ingin subset dataframe menggunakan berbagai kolom (misalnya antara 'C': 'E') . pandas.DataFrame.drop () tentu saja merupakan pilihan untuk mengelompokkan data berdasarkan daftar kolom yang ditentukan oleh pengguna (meskipun Anda harus berhati-hati bahwa Anda selalu menggunakan salinan kerangka data dan parameter inplace tidak boleh disetel ke True !!)

Pilihan lain adalah menggunakan pandas.columns.difference () , yang melakukan perbedaan set pada nama kolom, dan mengembalikan tipe indeks array yang berisi kolom yang diinginkan. Berikut ini solusinya:

df = pd.DataFrame([[2,3,4],[3,4,5]],columns=['a','b','c'],index=[1,2])
columns_for_differencing = ['a']
df1 = df.copy()[df.columns.difference(columns_for_differencing)]
print(df1)

Outputnya adalah: b c 1 3 4 2 4 5

Harshit
sumber
1
Salinan () tidak perlu. yaitu: df1 = df[df.columns.difference(columns_for_differencing)]akan mengembalikan dataframe baru / disalin. Anda akan dapat memodifikasi df1tanpa mengubah df. Terima kasih, btw. Inilah yang saya butuhkan.
Bazyli Debowski
4

Anda juga dapat menggunakan df.pop ()

>>> df = pd.DataFrame([('falcon', 'bird',    389.0),
...                    ('parrot', 'bird',     24.0),
...                    ('lion',   'mammal',   80.5),
...                    ('monkey', 'mammal', np.nan)],
...                   columns=('name', 'class', 'max_speed'))
>>> df
     name   class  max_speed
0  falcon    bird      389.0
1  parrot    bird       24.0
2    lion  mammal       80.5
3  monkey  mammal 

>>> df.pop('class')
0      bird
1      bird
2    mammal
3    mammal
Name: class, dtype: object

>>> df
     name  max_speed
0  falcon      389.0
1  parrot       24.0
2    lion       80.5
3  monkey        NaN

beri tahu saya jika ini membantu Anda, silakan gunakan df.pop (c)

Puneet Sinha
sumber
3

Saya telah melihat beberapa jawaban tentang itu, tetapi tetap tidak jelas bagi saya. Bagaimana Anda memilih kolom yang diminati? Jawabannya adalah jika Anda mengumpulkannya dalam daftar, Anda bisa merujuk kolom menggunakan daftar.

Contoh

print(extracted_features.shape)
print(extracted_features)

(63,)
['f000004' 'f000005' 'f000006' 'f000014' 'f000039' 'f000040' 'f000043'
 'f000047' 'f000048' 'f000049' 'f000050' 'f000051' 'f000052' 'f000053'
 'f000054' 'f000055' 'f000056' 'f000057' 'f000058' 'f000059' 'f000060'
 'f000061' 'f000062' 'f000063' 'f000064' 'f000065' 'f000066' 'f000067'
 'f000068' 'f000069' 'f000070' 'f000071' 'f000072' 'f000073' 'f000074'
 'f000075' 'f000076' 'f000077' 'f000078' 'f000079' 'f000080' 'f000081'
 'f000082' 'f000083' 'f000084' 'f000085' 'f000086' 'f000087' 'f000088'
 'f000089' 'f000090' 'f000091' 'f000092' 'f000093' 'f000094' 'f000095'
 'f000096' 'f000097' 'f000098' 'f000099' 'f000100' 'f000101' 'f000103']

Saya memiliki daftar berikut / array numpy extracted_features, menentukan 63 kolom. Dataset asli memiliki 103 kolom, dan saya ingin mengekstrak persisnya, kemudian saya akan gunakan

dataset[extracted_features]

Dan Anda akan berakhir dengan ini

masukkan deskripsi gambar di sini

Ini sesuatu yang akan Anda gunakan cukup sering dalam Pembelajaran Mesin (lebih khusus, dalam pemilihan fitur). Saya ingin membahas cara lain juga, tapi saya pikir itu sudah dibahas oleh stackoverflower lainnya. Semoga ini bermanfaat!

Kareem Jeiroudi
sumber
2

Anda dapat menggunakan pandas.DataFrame.filtermetode untuk memfilter atau menyusun ulang kolom seperti ini:

df1 = df.filter(['a', 'b'])
Ramin Melikov
sumber
0
df[['a','b']] # select all rows of 'a' and 'b'column 
df.loc[0:10, ['a','b']] # index 0 to 10 select column 'a' and 'b'
df.loc[0:10, ['a':'b']] # index 0 to 10 select column 'a' to 'b'
df.iloc[0:10, 3:5] # index 0 to 10 and column 3 to 5
df.iloc[3, 3:5] # index 3 of column 3 to 5
Biplob Das
sumber