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


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.