скидання нескінченних значень із фреймів даних у пандах?


220

який найшвидший / найпростіший спосіб скинути значення nan та inf / -inf з панд DataFrame без скидання mode.use_inf_as_null? Я хотів би мати можливість використовувати subsetі howаргументи dropna, крім infзначень, що вважаються відсутніми, наприклад:

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

це можливо? Чи є спосіб сказати, dropnaщоб включити infдо свого визначення пропущені значення?

Відповіді:


417

Найпростішим способом було б перше replaceвведення інформації в NaN:

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

а потім скористайтеся dropna:

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

Наприклад:

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

Цей же метод буде працювати і для серії.


2
Як можна "обміняти" infзначення на intтакі заздалегідь задані , як 0, наприклад , у певному стовпці?
3kstc

4
@ 3kstc використання .replace(..., 0). Щойно робити на стовпцях, ви оновлюєте ці стовпці, тобтоdf[cols] = df[cols].replace(..., 0)
Енді Хейден,

3
Можливо, варто уточнити, що replaceне працює на місці, тому DataFrameповертається нове
Marco

36

З контекстом опції це можливо без постійної настройки use_inf_as_na. Наприклад:

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

Звичайно, це може бути налаштовано на лікування, infяк NaNпостійно

pd.set_option('use_inf_as_na', True)

Для старих версій замініть use_inf_as_naна use_inf_as_null.


6
Це найпрочитаніша відповідь і, отже, найкраща, хоча вона буквально (але не по духу) порушує оригінальне запитання.
ijoseph

2
Панди станом на (принаймні) 0,24: use_inf_as_nullзастарілі і будуть видалені в наступній версії. Використовуйте use_inf_as_naзамість цього. Додати / оновити відповідь?
Гокон Т.

1
Цей варіант є кращим вибором, який слід розглядати infяк нулі на загальносвітових рівнях замість операційного. Це потенційно може економити час спочатку, вводячи значення.
TaoPR

15

Ось ще один метод, що використовує .locдля заміни inf на nan на серію:

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

Отже, у відповідь на початкове запитання:

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

11

Використання (швидке та просте):

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

Ця відповідь заснована на відповіді Дугра в іншому запитанні. Ось приклад коду:

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

Результат:

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

7

Ще одним рішенням буде використання isinметоду. Використовуйте його для визначення того, чи є кожне значення нескінченним чи відсутнім, а потім ланцюжком allметоду визначте, чи всі значення у рядках нескінченні чи відсутні.

Нарешті, використовуйте заперечення цього результату для вибору рядків, які не мають усіх нескінченних чи відсутніх значень за допомогою булевої індексації.

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

7

Вищевказане рішення дозволить змінити infs, які відсутні в цільових стовпцях. Щоб виправити це,

lst = [np.inf, -np.inf]
to_replace = {v: lst for v in ['col1', 'col2']}
df.replace(to_replace, np.nan)

3
python 2.7 і вище розуміння диктанту підтримки:{v: lst for v in cols}
Aryeh Leib Taurog

4

Ви можете використовувати pd.DataFrame.maskз np.isinf. Спершу слід переконатися, що ваші серії даних є типовими float. Потім використовуйте dropnaсвою існуючу логіку.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.