Menghapus baris DataFrame di Panda berdasarkan nilai kolom

511

Saya memiliki DataFrame berikut:

             daysago  line_race rating        rw    wrating
 line_date                                                 
 2007-03-31       62         11     56  1.000000  56.000000
 2007-03-10       83         11     67  1.000000  67.000000
 2007-02-10      111          9     66  1.000000  66.000000
 2007-01-13      139         10     83  0.880678  73.096278
 2006-12-23      160         10     88  0.793033  69.786942
 2006-11-09      204          9     52  0.636655  33.106077
 2006-10-22      222          8     66  0.581946  38.408408
 2006-09-29      245          9     70  0.518825  36.317752
 2006-09-16      258         11     68  0.486226  33.063381
 2006-08-30      275          8     72  0.446667  32.160051
 2006-02-11      475          5     65  0.164591  10.698423
 2006-01-13      504          0     70  0.142409   9.968634
 2006-01-02      515          0     64  0.134800   8.627219
 2005-12-06      542          0     70  0.117803   8.246238
 2005-11-29      549          0     70  0.113758   7.963072
 2005-11-22      556          0     -1  0.109852  -0.109852
 2005-11-01      577          0     -1  0.098919  -0.098919
 2005-10-20      589          0     -1  0.093168  -0.093168
 2005-09-27      612          0     -1  0.083063  -0.083063
 2005-09-07      632          0     -1  0.075171  -0.075171
 2005-06-12      719          0     69  0.048690   3.359623
 2005-05-29      733          0     -1  0.045404  -0.045404
 2005-05-02      760          0     -1  0.039679  -0.039679
 2005-04-02      790          0     -1  0.034160  -0.034160
 2005-03-13      810          0     -1  0.030915  -0.030915
 2004-11-09      934          0     -1  0.016647  -0.016647

Saya perlu menghapus baris line_raceyang sama dengan 0. Apa cara paling efisien untuk melakukan ini?

TravisVOX
sumber

Jawaban:

878

Jika saya memahami dengan benar, itu harus sesederhana:

df = df[df.line_race != 0]
tshauck
sumber
16
Akankah ini membutuhkan lebih banyak memori jika dfbesar? Atau, bisakah saya melakukannya di tempat?
ziyuang
10
Hanya menjalankannya dfdengan baris 2M dan berjalan cukup cepat.
Dror
46
@vfxGer jika ada spasi di kolom, seperti 'perlombaan garis', maka Anda bisa melakukannyadf = df[df['line race'] != 0]
Paul
3
Bagaimana kita akan memodifikasi perintah ini jika kita ingin menghapus seluruh baris jika nilai yang dimaksud ditemukan di salah satu kolom di baris itu?
Alex
3
Terima kasih! Fwiw, bagi saya ini harusdf=df[~df['DATE'].isin(['2015-10-30.1', '2015-11-30.1', '2015-12-31.1'])]
citynorman
182

Tetapi untuk setiap bypasser masa depan Anda dapat menyebutkan bahwa df = df[df.line_race != 0]tidak melakukan apa-apa ketika mencoba memfilter None/ menghilangkan nilai.

Apakah berhasil:

df = df[df.line_race != 0]

Tidak melakukan apa-apa:

df = df[df.line_race != None]

Apakah berhasil:

df = df[df.line_race.notnull()]
wonderkid2
sumber
4
bagaimana cara melakukannya jika kita tidak tahu nama kolomnya?
Piyush S. Wanare
Bisa saja df = df[df.columns[2].notnull()], tetapi dengan satu atau lain cara Anda harus dapat mengindeks kolom entah bagaimana.
erekalper
1
df = df[df.line_race != 0]menjatuhkan baris tetapi juga tidak mengatur ulang indeks. Jadi, ketika Anda menambahkan baris lain di df mungkin tidak menambahkan di akhir. Saya akan merekomendasikan pengaturan ulang indeks setelah operasi itu ( df = df.reset_index(drop=True))
the_new_james
Anda tidak boleh membandingkan dengan Tidak Ada dengan ==operator untuk memulai. stackoverflow.com/questions/3257919/…
Bram Vanroy
40

Cara terbaik untuk melakukan ini adalah dengan masking boolean:

In [56]: df
Out[56]:
     line_date  daysago  line_race  rating    raw  wrating
0   2007-03-31       62         11      56  1.000   56.000
1   2007-03-10       83         11      67  1.000   67.000
2   2007-02-10      111          9      66  1.000   66.000
3   2007-01-13      139         10      83  0.881   73.096
4   2006-12-23      160         10      88  0.793   69.787
5   2006-11-09      204          9      52  0.637   33.106
6   2006-10-22      222          8      66  0.582   38.408
7   2006-09-29      245          9      70  0.519   36.318
8   2006-09-16      258         11      68  0.486   33.063
9   2006-08-30      275          8      72  0.447   32.160
10  2006-02-11      475          5      65  0.165   10.698
11  2006-01-13      504          0      70  0.142    9.969
12  2006-01-02      515          0      64  0.135    8.627
13  2005-12-06      542          0      70  0.118    8.246
14  2005-11-29      549          0      70  0.114    7.963
15  2005-11-22      556          0      -1  0.110   -0.110
16  2005-11-01      577          0      -1  0.099   -0.099
17  2005-10-20      589          0      -1  0.093   -0.093
18  2005-09-27      612          0      -1  0.083   -0.083
19  2005-09-07      632          0      -1  0.075   -0.075
20  2005-06-12      719          0      69  0.049    3.360
21  2005-05-29      733          0      -1  0.045   -0.045
22  2005-05-02      760          0      -1  0.040   -0.040
23  2005-04-02      790          0      -1  0.034   -0.034
24  2005-03-13      810          0      -1  0.031   -0.031
25  2004-11-09      934          0      -1  0.017   -0.017

In [57]: df[df.line_race != 0]
Out[57]:
     line_date  daysago  line_race  rating    raw  wrating
0   2007-03-31       62         11      56  1.000   56.000
1   2007-03-10       83         11      67  1.000   67.000
2   2007-02-10      111          9      66  1.000   66.000
3   2007-01-13      139         10      83  0.881   73.096
4   2006-12-23      160         10      88  0.793   69.787
5   2006-11-09      204          9      52  0.637   33.106
6   2006-10-22      222          8      66  0.582   38.408
7   2006-09-29      245          9      70  0.519   36.318
8   2006-09-16      258         11      68  0.486   33.063
9   2006-08-30      275          8      72  0.447   32.160
10  2006-02-11      475          5      65  0.165   10.698

UPDATE: Sekarang panda 0.13 sudah keluar, cara lain untuk melakukan ini adalah df.query('line_race != 0').

Phillip Cloud
sumber
df.query terlihat sangat berguna! Terima kasih! pandas.pydata.org/pandas-docs/version/0.13.1/generated/…
fantabolous
14
Pembaruan bagus untuk query. Ini memungkinkan untuk kriteria seleksi yang lebih kaya (mis. Operasi seperti set seperti di df.query('variable in var_list')mana 'var_list' adalah daftar nilai yang diinginkan)
philE
1
bagaimana ini bisa dicapai jika nama kolom memiliki spasi dalam nama?
iNoob
2
querytidak terlalu berguna jika nama kolom memiliki spasi di dalamnya.
Phillip Cloud
3
Saya akan menghindari memiliki ruang di header dengan sesuatu seperti inidf = df.rename(columns=lambda x: x.strip().replace(' ','_'))
Scientist1642
40

hanya untuk menambahkan solusi lain, khususnya berguna jika Anda menggunakan penilai panda baru, solusi lain akan menggantikan panda asli dan kehilangan penilai.

df.drop(df.loc[df['line_race']==0].index, inplace=True)
desmond
sumber
1
apa tujuan penulisan indeks dan inplace. Adakah yang bisa menjelaskannya?
heman123
2
Baca dokumen!
Federico Corazza
Saya pikir kita perlu .reset_index()juga jika seseorang akhirnya menggunakan
pengakses
17

Jika Anda ingin menghapus baris berdasarkan beberapa nilai kolom, Anda dapat menggunakan:

df[(df.line_race != 0) & (df.line_race != 10)]

Untuk menjatuhkan semua baris dengan nilai 0 dan 10 untuk line_race.

Robvh
sumber
Apakah ada cara yang lebih efisien untuk melakukan ini jika Anda memiliki beberapa nilai yang ingin Anda hilangkan yaitu, drop = [0, 10]dan kemudian sesuatu sepertidf[(df.line_race != drop)]
mikey
14

Jawaban yang diberikan adalah benar tanpa batas karena seseorang di atas mengatakan Anda dapat menggunakan df.query('line_race != 0')yang tergantung pada masalah Anda jauh lebih cepat. Sangat disarankan.

h3h325
sumber
Terutama membantu jika Anda memiliki DataFramenama variabel panjang seperti saya (dan, saya berani menebak, semua orang dibandingkan dengan yang dfdigunakan untuk contoh), karena Anda hanya perlu menulisnya sekali.
ijoseph
9

Meskipun jawaban sebelumnya hampir mirip dengan apa yang akan saya lakukan, tetapi menggunakan metode indeks tidak memerlukan menggunakan metode pengindeksan lain .loc (). Hal ini dapat dilakukan dengan cara yang sama tetapi tepat seperti

df.drop(df.index[df['line_race'] == 0], inplace = True)
Loochie
sumber
1
Di tempat solusi lebih baik untuk dataset besar atau memori terbatas. +1
davmor
3

Cara lain untuk melakukannya. Mungkin bukan cara yang paling efisien karena kode itu terlihat sedikit lebih kompleks daripada kode yang disebutkan dalam jawaban lain, tetapi masih merupakan cara alternatif untuk melakukan hal yang sama.

  df = df.drop(df[df['line_race']==0].index)
Amruth Lakkavaram
sumber
1

Saya mengkompilasi dan menjalankan kode saya. Ini adalah kode yang akurat. Anda bisa mencobanya sendiri.

data = pd.read_excel('file.xlsx')

Jika Anda memiliki karakter atau spasi khusus dalam nama kolom, Anda dapat menuliskannya ''seperti pada kode yang diberikan:

data = data[data['expire/t'].notnull()]
print (date)

Jika hanya ada satu nama kolom string tanpa spasi atau karakter khusus, Anda dapat langsung mengaksesnya.

data = data[data.expire ! = 0]
print (date)
Uzair
sumber
0

Hanya menambahkan cara lain untuk DataFrame diperluas ke semua kolom:

for column in df.columns:
   df = df[df[column]!=0]

Contoh:

def z_score(data,count):
   threshold=3
   for column in data.columns:
       mean = np.mean(data[column])
       std = np.std(data[column])
       for i in data[column]:
           zscore = (i-mean)/std
           if(np.abs(zscore)>threshold):
               count=count+1
               data = data[data[column]!=i]
   return data,count
Prateek Kumar Singh
sumber