Pandas DataFrame에서 잘못된 값을 None으로 바꿉니다.


80

NonePython의 Pandas에서 값을 대체하는 방법이 있습니까?

df.replace('pre', 'post')값을 사용 하고 다른 값으로 바꿀 수 있지만 None값 으로 바꾸고 싶은 경우에는 할 수 없습니다. 시도하면 이상한 결과가 나타납니다.

그래서 여기에 예가 있습니다 :

df = DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df.replace('-', 0)

성공적인 결과를 반환합니다.

그러나,

df.replace('-', None)

다음 결과를 반환합니다.

0
0   - // this isn't replaced
1   3
2   2
3   5
4   1
5  -5
6  -1
7  -1 // this is changed to `-1`...
8   9

왜 그런 이상한 결과가 반환됩니까?

이 데이터 프레임을 MySQL 데이터베이스에 붓고 싶기 때문에 데이터 프레임의 NaN어떤 요소에도 값을 넣을 수없고 대신 None. 확실히, 먼저 변경할 수 있습니다 '-'NaN다음 변환 NaNNone,하지만 난 dataframe 그런 끔찍한 방법으로 역할을 이유를 알고 싶습니다.

Python 2.7 및 OS X 10.8의 Pandas 0.12.0 dev에서 테스트되었습니다. Python은 OS X에 사전 설치된 버전이며 정보를 위해 SciPy Superpack 스크립트를 사용하여 pandas를 설치했습니다.


합니까 write_frame하지 구문 분석 NaN에들 none들?
Andy Hayden

예. InternalError: (1054, u"Unknown column 'nan' in 'field list'")오류 가 발생했습니다. 메서드 를 실행 NaN하기 None전에 변환 하는 것 외에 다른 솔루션에 대해 알지 못합니다 write_frame.
Blaszard 2013-06-13

어떤 버전의 팬더를 사용하고 있습니까?
Andy Hayden

Scipy 슈퍼 팩은 개발자를 제공합니까? 좋아, 나는 당신 이 이것을 github에 대한 문제로 제기 해야한다고 생각합니다 . 수정하기가 너무 어렵지 않아야합니다.
Andy Hayden

CSV / Excel에서이 데이터를 읽는 경우na_values 인수를 사용하여 이러한 값을 NaN으로 읽을 수 있습니다 . 이 답변에 대한 자세한 정보.
cs95

답변:


111

실제로 이후 버전의 pandas에서는 TypeError가 발생합니다.

df.replace('-', None)
TypeError: If "to_replace" and "value" are both None then regex must be a mapping

목록이나 사전을 전달하여 수행 할 수 있습니다.

In [11]: df.replace('-', df.replace(['-'], [None]) # or .replace('-', {0: None})
Out[11]:
      0
0  None
1     3
2     2
3     5
4     1
5    -5
6    -1
7  None
8     9

그러나 None보다는 NaN을 사용하는 것이 좋습니다.

In [12]: df.replace('-', np.nan)
Out[12]:
     0
0  NaN
1    3
2    2
3    5
4    1
5   -5
6   -1
7  NaN
8    9

15
또는 단순히 목록, 예를 들어 df.replace(['-'], [None]), 또는 df.replace({'-': None})라고 생각합니다. 사용 None센티넬 배제 너무 값으로 사용하는 등 ..
DSM

@ user2360798 replace는 실제로 매우 기능이 풍부한 (복잡한 읽기) 기능이지만 (dev) docstring 은 정말 좋습니다.
Andy Hayden

4
그것이 명백한 dfdf = df.replace({'?': np.nan})
지는 모르겠지만

3
@AndyHayden df.replace('-', df.replace(['-'], [None])은 펑키 해 보입니다. 오타인가요?
lin_bug

2
@lin_bug 최근 판다 버전에서는 더 이상 작동하지 않는 것 같습니다. df.where (df! = '-', None) 작동합니다
Andy Hayden

17

단순함과 우아함 replace으로 dict인해 사용하는 솔루션을 선호합니다 .

df.replace({'-': None})

더 많은 대체품을 가질 수도 있습니다.

df.replace({'-': None, 'None': None})

그리고 더 큰 교체의 경우에도 무엇이 무엇으로 교체되는지는 항상 분명하고 명확합니다. 내 생각에는 긴 목록의 경우 훨씬 더 어렵습니다.


1
이 기술이 작동하는 이유 중 일부는 dictin 형식을 사용 to_replace하면 method매개 변수가 평가되지 않으므로 method='pad'기본값이 나쁜 영향을 미치지 않는다는 점에 주목할 가치가 있습니다 .
bsplosion

15

where아마도 당신이 찾고있는 것입니다. 그래서

data=data.where(data=='-', None) 

로부터 팬더 문서 :

where [반환] self와 모양이 같고 해당 항목이 self에서 왔으며 cond가 True이고 그렇지 않으면 other에서 온 객체).


5
이것은 실제로 부정확합니다. data = data.where (data == '-', None)은 '-'와 같지 않은 모든 것을 None으로 바꿉니다. 여기서 Pandas 버전은 첫 번째 인수 (이 경우 data == '-')의 값을 유지하고 다른 것은 두 번째 인수 (이 경우 None)로 대체합니다. np.where가 첫 번째 인수에서 조건문을 요청하고 두 번째 인수에서 true 인 경우, 세 번째 인수에서 false 인 경우를 요청한다는 점에서 좀 더 명시 적이기 때문에 약간 혼란 스럽습니다.
clg4

8

이 게시물을 진행하기 전에 NaN과 None의 차이점 을 이해 하는 것이 중요합니다 . 하나는 float 유형이고 다른 하나는 객체 유형입니다. Pandas는 이러한 유형에 대한 많은 메서드를 벡터화 할 수 있으므로 스칼라 유형 작업에 더 적합합니다. Pandas는 None과 NaN을 일관되게 처리하려고하지만 NumPy는 처리 할 수 ​​없습니다.

내 제안 ( and Andy 's )은 NaN을 고수하는 것입니다.

하지만 질문에 답하려면 ...

pandas> = 0.18 : na_values=['-']인수 사용read_csv

이 데이터를 CSV / Excel에서로드했다면 좋은 소식이 있습니다. 후속 단계로 코드를 사용하여 수정 사항을 작성하는 대신 데이터로드 중에 루트에서이를 처리 할 수 ​​있습니다.

대부분의 pd.read_*함수 ( read_csv및 등 read_excel)는 na_values속성을 허용 합니다.

file.csv

A,B
-,1
3,-
2,-
5,3
1,-2
-5,4
-1,-1
-,0
9,0

이제 -문자를 NaN 으로 변환하려면 다음을 수행하십시오.

import pandas as pd
df = pd.read_csv('file.csv', na_values=['-'])
df

     A    B
0  NaN  1.0
1  3.0  NaN
2  2.0  NaN
3  5.0  3.0
4  1.0 -2.0
5 -5.0  4.0
6 -1.0 -1.0
7  NaN  0.0
8  9.0  0.0

다른 기능 / 파일 형식에 대해서도 유사합니다.

추신 : v0.24 +에서는 열에 NaN이 있어도 정수 유형을 유지할 수 있습니다 (예, 케이크를 먹고 먹는 것에 대해서도 이야기하십시오). 지정할 수 있습니다dtype='Int32'

df = pd.read_csv('file.csv', na_values=['-'], dtype='Int32')
df

     A    B
0  NaN    1
1    3  NaN
2    2  NaN
3    5    3
4    1   -2
5   -5    4
6   -1   -1
7  NaN    0
8    9    0

df.dtypes

A    Int32
B    Int32
dtype: object

dtype은 일반적인 int 유형이 아니라 Nullable Integer 유형입니다. 다른 옵션이 있습니다.


숫자 데이터 처리 : pd.to_numericwitherrors='coerce

숫자 데이터를 다루는 경우 더 빠른 해결책은 인수 pd.to_numeric와 함께 사용하는 것 입니다.이 errors='coerce'인수는 유효하지 않은 값 (숫자로 캐스트 할 수없는 값)을 NaN으로 강제합니다.

pd.to_numeric(df['A'], errors='coerce')

0    NaN
1    3.0
2    2.0
3    5.0
4    1.0
5   -5.0
6   -1.0
7    NaN
8    9.0
Name: A, dtype: float64

(널 가능) 정수 dtype을 유지하려면 다음을 사용하십시오.

pd.to_numeric(df['A'], errors='coerce').astype('Int32')

0    NaN
1      3
2      2
3      5
4      1
5     -5
6     -1
7    NaN
8      9
Name: A, dtype: Int32 

여러 열을 강제하려면 다음을 사용하십시오 apply.

df[['A', 'B']].apply(pd.to_numeric, errors='coerce').astype('Int32')

     A    B
0  NaN    1
1    3  NaN
2    2  NaN
3    5    3
4    1   -2
5   -5    4
6   -1   -1
7  NaN    0
8    9    0

... 결과를 다시 할당합니다.

자세한 내용은 이 답변 에서 찾을 수 있습니다 .


3
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df = df.where(df!='-', None)

0

null 값 설정은 다음을 사용하여 수행 할 수 있습니다 np.nan.

import numpy as np
df.replace('-', np.nan)

장점은 df.last_valid_index()이들을 유효하지 않은 것으로 인식 한다는 것 입니다.


0

교체 사용 및 새 df 할당 :

import pandas as pd
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9])
dfnew = df.replace('-', 0)
print(dfnew)


(venv) D:\assets>py teste2.py
   0
0  0
1  3
2  2
3  5
4  1
5 -5

0
df.replace('-', np.nan).astype("object")

이렇게하면 isnull()나중에 데이터 프레임에서 사용할 수 있습니다.


0

Pandas 버전 ≥1.0.0에서는 DataFrame.replace또는 Series.replace다음을 사용합니다 .

df.replace(old_val, pd.NA, inplace=True)

다음 두 가지 이유로 더 좋습니다.

  1. 또는 pd.NA대신 사용 합니다 .Nonenp.nan
  2. 더 많은 메모리를 효율적으로 사용할 수있는 제자리 대체합니다 .
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.