กำลังลดค่าอนันต์จากดาต้าเฟรมในนุ่น?


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ไว้ในนิยามของค่าที่หายไปหรือไม่?

คำตอบ:


418

วิธีที่ง่ายที่สุดคือการ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
@ .replace(..., 0)ใช้ ในการทำคอลัมน์คุณต้องอัปเดตคอลัมน์เหล่านั้นเช่นdf[cols] = df[cols].replace(..., 0)
Andy Hayden

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_nause_inf_as_null


6
นี่เป็นคำตอบที่อ่านง่ายที่สุดและเป็นคำตอบที่ดีที่สุดแม้ว่าจะเป็นการละเมิดตัวอักษร (แต่ไม่ใช่ในจิตวิญญาณ) ของคำถามดั้งเดิม
ijoseph

2
นุ่น ณ (อย่างน้อย) 0.24: use_inf_as_nullเลิกใช้แล้วและจะถูกลบออกในเวอร์ชันต่อไป ใช้use_inf_as_naแทน เพิ่มไปยัง / อัปเดตคำตอบ?
Håkon T.

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)]

คำตอบนี้ขึ้นอยู่กับคำตอบของ DougRในคำถามอื่น นี่คือตัวอย่างรหัส:

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
หลาม 2.7 และสูงกว่ารองรับความเข้าใจ dict:{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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.