menjatuhkan nilai tak terbatas dari dataframe di panda?

219

apa cara tercepat / paling sederhana untuk menjatuhkan nilai nan dan inf / -inf dari panda DataFrame tanpa mengatur ulang mode.use_inf_as_null? Saya ingin dapat menggunakan argumen subsetdan , kecuali dengan nilai yang dianggap hilang, seperti:howdropnainf

df.dropna(subset=["col1", "col2"], how="all", with_inf=True)

apakah ini mungkin? Apakah ada cara untuk mengatakan dropnauntuk memasukkan infdalam definisi nilai yang hilang?


sumber

Jawaban:

416

Cara paling sederhana adalah dengan replaceinf pertama ke NaN:

df.replace([np.inf, -np.inf], np.nan)

dan kemudian gunakan dropna:

df.replace([np.inf, -np.inf], np.nan).dropna(subset=["col1", "col2"], how="all")

Sebagai contoh:

In [11]: df = pd.DataFrame([1, 2, np.inf, -np.inf])

In [12]: df.replace([np.inf, -np.inf], np.nan)
Out[12]:
    0
0   1
1   2
2 NaN
3 NaN

Metode yang sama akan bekerja untuk suatu Seri.

Andy Hayden
sumber
2
Bagaimana seseorang bisa "menukar" infnilai - nilai ke yang telah ditentukan intseperti 0, di kolom tertentu?
3kstc
4
@ Penggunaan 3kstc .replace(..., 0). Untuk melakukan pada kolom Anda memperbarui kolom-kolom yaitudf[cols] = df[cols].replace(..., 0)
Andy Hayden
3
Mungkin ada baiknya untuk menentukan bahwa replacetidak berfungsi di tempat, jadi yang baru DataFramedikembalikan
Marco
36

Dengan konteks opsi, ini dimungkinkan tanpa pengaturan secara permanen use_inf_as_na. Sebagai contoh:

with pd.option_context('mode.use_inf_as_na', True):
    df = df.dropna(subset=['col1', 'col2'], how='all')

Tentu saja dapat diatur untuk memperlakukan infsebagai NaNpermanen dengan

pd.set_option('use_inf_as_na', True)

Untuk versi yang lebih lama, ganti use_inf_as_nadengan use_inf_as_null.

ayhan
sumber
6
Ini adalah jawaban yang paling mudah dibaca dan akibatnya adalah yang terbaik, meskipun itu melanggar dalam surat (tetapi tidak dalam semangat) pertanyaan aslinya.
ijoseph
2
Panda pada (setidaknya) 0,24: use_inf_as_nulltelah ditinggalkan dan akan dihapus dalam versi yang akan datang. Gunakan use_inf_as_nasebagai gantinya. Tambahkan ke / perbarui jawaban?
Håkon T.
1
Yang ini adalah pilihan yang lebih baik untuk diperlakukan infsebagai nol di tingkat pengaturan global daripada tingkat operasional. Ini berpotensi menghemat waktu untuk memasukkan nilai terlebih dahulu.
TaoPR
15

Berikut adalah metode lain yang digunakan .locuntuk mengganti inf dengan nan pada Seri:

s.loc[(~np.isfinite(s)) & s.notnull()] = np.nan

Jadi, dalam menanggapi pertanyaan awal:

df = pd.DataFrame(np.ones((3, 3)), columns=list('ABC'))

for i in range(3): 
    df.iat[i, i] = np.inf

df
          A         B         C
0       inf  1.000000  1.000000
1  1.000000       inf  1.000000
2  1.000000  1.000000       inf

df.sum()
A    inf
B    inf
C    inf
dtype: float64

df.apply(lambda s: s[np.isfinite(s)].dropna()).sum()
A    2
B    2
C    2
dtype: float64
Alexander
sumber
11

Gunakan (cepat dan sederhana):

df = df[np.isfinite(df).all(1)]

Jawaban ini didasarkan pada jawaban DougR dalam pertanyaan lain. Berikut contoh kode:

import pandas as pd
import numpy as np
df=pd.DataFrame([1,2,3,np.nan,4,np.inf,5,-np.inf,6])
print('Input:\n',df,sep='')
df = df[np.isfinite(df).all(1)]
print('\nDropped:\n',df,sep='')

Hasil:

Input:
    0
0  1.0000
1  2.0000
2  3.0000
3     NaN
4  4.0000
5     inf
6  5.0000
7    -inf
8  6.0000

Dropped:
     0
0  1.0
1  2.0
2  3.0
4  4.0
6  5.0
8  6.0
Markus Dutschke
sumber
7

Namun solusi lain adalah dengan menggunakan isinmetode ini. Gunakan untuk menentukan apakah setiap nilai tidak terbatas atau hilang dan kemudian rantai allmetode untuk menentukan apakah semua nilai dalam baris tidak terbatas atau hilang.

Akhirnya, gunakan negasi dari hasil itu untuk memilih baris yang tidak memiliki semua nilai tak terbatas atau hilang melalui pengindeksan boolean.

all_inf_or_nan = df.isin([np.inf, -np.inf, np.nan]).all(axis='columns')
df[~all_inf_or_nan]
Ted Petrou
sumber
7

Solusi di atas akan memodifikasi infs yang tidak ada di kolom target. Untuk memperbaiki itu,

lst = [np.inf, -np.inf]
to_replace = {v: lst for v in ['col1', 'col2']}
df.replace(to_replace, np.nan)
has2k1
sumber
3
python 2.7 dan pemahaman dict dukungan yang lebih tinggi:{v: lst for v in cols}
Aryeh Leib Taurog
4

Anda bisa menggunakannya pd.DataFrame.maskbersama np.isinf. Anda harus memastikan terlebih dahulu seri dataframe Anda semuanya bertipe float. Kemudian gunakan dropnadengan logika Anda yang ada.

print(df)

       col1      col2
0 -0.441406       inf
1 -0.321105      -inf
2 -0.412857  2.223047
3 -0.356610  2.513048

df = df.mask(np.isinf(df))

print(df)

       col1      col2
0 -0.441406       NaN
1 -0.321105       NaN
2 -0.412857  2.223047
3 -0.356610  2.513048
jpp
sumber