팬더에서 공백 값 (공백)을 NaN으로 바꾸기


150

공백 (임의의 양)을 포함하는 Pandas 데이터 프레임에서 모든 값을 찾고 해당 값을 NaN으로 바꾸고 싶습니다.

이것이 어떻게 개선 될 수있는 아이디어가 있습니까?

기본적으로 나는 이것을 돌리고 싶다 :

                   A    B    C
2000-01-01 -0.532681  foo    0
2000-01-02  1.490752  bar    1
2000-01-03 -1.387326  foo    2
2000-01-04  0.814772  baz     
2000-01-05 -0.222552         4
2000-01-06 -1.176781  qux     

이것으로 :

                   A     B     C
2000-01-01 -0.532681   foo     0
2000-01-02  1.490752   bar     1
2000-01-03 -1.387326   foo     2
2000-01-04  0.814772   baz   NaN
2000-01-05 -0.222552   NaN     4
2000-01-06 -1.176781   qux   NaN

아래 코드를 사용하여 관리했지만 사람이 못 생겼습니다. 그것은 Pythonic이 아니며 팬더를 가장 효율적으로 사용하지 않는다고 확신합니다. 각 열을 반복하고 공백에 일치하는 각 값의 정규식 검색을 수행하는 함수를 적용하여 생성 된 열 마스크에 대해 부울 대체를 수행합니다.

for i in df.columns:
    df[i][df[i].apply(lambda i: True if re.search('^\s*$', str(i)) else False)]=None

빈 문자열을 포함 할 수있는 필드 만 반복하여 약간 최적화 할 수 있습니다.

if df[i].dtype == np.dtype('object')

하지만 그다지 개선되지는 않았습니다.

그리고 마지막으로,이 코드는 팬더 '기능처럼 작동 없음에 대상 문자열을 설정 fillna()하지만, 만약 내가 할 수 실제로 삽입 완전성에 대한 좋은 것 NaN대신 직접 None.


2
당신이 정말로 원하는 것은 replace정규식과 함께 사용 하는 것입니다 ... (아마도 이것은 기능으로 요청해야합니다).
Andy Hayden

3
이 기능에 대해 github 문제를 만들었습니다 : github.com/pydata/pandas/issues/2285 . PR에게 감사합니다! :)
Chang She

하나의 공백 문자를 잃어버린 것으로 정확하게 바꾸려면 아래의 간단한 해결책을 참조하십시오
Ted Petrou

답변:


198

팬더 0.13df.replace() 부터 일을 한다고 생각 합니다 .

df = pd.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'foo', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', '  '],         
], columns='A B C'.split(), index=pd.date_range('2000-01-01','2000-01-06'))

# replace field that's entirely space (or empty) with NaN
print(df.replace(r'^\s*$', np.nan, regex=True))

생산 :

                   A    B   C
2000-01-01 -0.532681  foo   0
2000-01-02  1.490752  bar   1
2000-01-03 -1.387326  foo   2
2000-01-04  0.814772  baz NaN
2000-01-05 -0.222552  NaN   4
2000-01-06 -1.176781  qux NaN

으로 Temak이 그것을 지적 사용하는 df.replace(r'^\s+$', np.nan, regex=True)경우에 대비하여 유효한 데이터가 공백이 포함되어 있습니다.


1
정규식은 부울 플래그입니다. 어쩌면 당신은 의미 pd.Series(["1", "#", "9", " .", None]).replace(r"( +\.)|#", "X", regex=True).values주는['1', 'X', '9', 'X', None]
patricksurry

2
2 년 후, 나는 판다가 그것을 지원하기 때문에 받아 들인 대답을 이것으로 바꿨습니다. 감사!
Chris Clark

35
참고 : 중간에 공간을 포함하는 요소를 NaN으로 대체하지 않으려면df.replace(r'^\s+$', np.nan, regex=True)
Temak

7
나는 이것을 사용하려고했지만 r '^ \ s * $'가 사용할 표현이어야한다는 것을 알았습니다. ^와 $가 없으면 두 개의 연속 공백이있는 문자열과 일치합니다. NaN으로 변환 할 것들의 목록에 빈 문자열 ""을 포함하도록 +에서 *로 변경됨
Master Yogurt

1
내 코드에서 솔루션을 시도하고 있지만 효과가 없습니다. "에너지 ["에너지 공급 "] .replace (to_replace ="... ", value = np.NaN)"를 시도하고 있습니다. 문자열 "..."을 NaN 값으로 변경하려고하지만 아무것도하지 않고 동일한 데이터 프레임을 반환합니다.
Archan Joshi

50

빈 문자열과 레코드를 공백으로 바꾸려면 올바른 대답은 !입니다.

df = df.replace(r'^\s*$', np.nan, regex=True)

허용 된 답변

df.replace(r'\s+', np.nan, regex=True)

빈 문자열을 대체하지 않습니다! 주어진 약간의 예제를 사용하여 시도해 볼 수 있습니다.

df = pd.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'fo o', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', ''],         
], columns='A B C'.split(), index=pd.date_range('2000-01-01','2000-01-06'))

또한 'fo o'는 공백을 포함하지만 Nan으로 대체되지 않습니다. 더 간단한 점은 다음과 같습니다.

df.replace(r'', np.NaN)

작동하지 않습니다-사용해보십시오.


33

어때요?

d = d.applymap(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)

applymap함수는 함수를 데이터 프레임의 모든 셀에 적용합니다.


정말 좋은 개선입니다! 나는 이것을 회고하여 생각해야했지만 어떤 이유로 부울 교체를하는 것에 매달렸다. 한 가지 질문-기본 문자열 검사와 str (x) .isspace () 비교의 이점이 있습니까?
Chris Clark

1
@ChrisClark : isinstance조금 더 빠를 것이라고 생각하지만, 어느 쪽이든 괜찮습니다 .
BrenBarn

13
위 코드에서 "basestring"에 대한 참조는 Python 3에서 작동하지 않습니다.이 경우 "str"을 대신 사용해보십시오.
스파이크 윌리엄스

4
이 솔루션은 빈 문자열을 대체하지 않습니다 ''. 빈 문자열도 고려하려면 다음을 사용하십시오.d = d.applymap(lambda x: np.nan if isinstance(x, basestring) and (not x or x.isspace()) else x)
tuomastik

18

나는 이것을 할 것이다 :

df = df.apply(lambda x: x.str.strip()).replace('', np.nan)

또는

df = df.apply(lambda x: x.str.strip() if isinstance(x, str) else x).replace('', np.nan)

모든 str을 제거한 다음 빈 str을로 바꿉니다 np.nan.


람다 x : x.str.strip ()은 람다 x : x.strip ()이어야합니까? 작은 제안 : 앞에 .astype (str)을 추가하면 다른 데이터 문제가 해결됩니다. 이것은 나를 위해 작동합니다 : df = df.apply [ 'column']. astype (str) .apply (lambda x : x.strip ()). replace ( '', np.nan)
Wouter

두 번째 코드 행은 int / float 및 string 유형 열을 모두 처리합니다. 좋은. Tks!
Kate Stohr 2016 년


5

CSV 파일에서 데이터를 내보내는 경우 다음과 같이 간단 할 수 있습니다.

df = pd.read_csv(file_csv, na_values=' ')

이렇게하면 데이터 프레임이 생성되고 빈 값이 Na로 바뀝니다.


2
또 다른 옵션 ..using skipinitialspace=True을 사용하면 구분 기호 뒤에 공백이 없어 지므로 공백이 있으면 빈 문자열을로 읽습니다 nan. 그러나 어떤 이유로 든 초기 공간을 유지하려면이 옵션을 선택하지 마십시오.
Rajshekar Reddy

1
@RajshekarReddy 당신은 이것을 어딘가에 답으로 넣을 수 있습니까, 이것은 훌륭했습니다!
User2321

2

단일 값에 대해 동등성을 검사하는 매우 빠르고 간단한 솔루션의 경우이 mask방법을 사용할 수 있습니다 .

df.mask(df == ' ')

1

이것들은 모두 정답에 가깝지만 문제를 해결하는 동안 다른 사람들이 코드를 읽는 것이 가장 읽기 쉬운 상태라고 말하지는 않습니다. 대답은 BrenBarn의 답변 과 해당 답변 아래의 tuomasttik의 의견 이 결합되어 있다고 말하고 싶습니다 . BrenBarn의 답변은 isspace내장 기능을 사용하지만 OP 요청에 따라 빈 문자열 제거를 지원하지 않으며 문자열을 null로 대체하는 표준 사용 사례로 간주하는 경향이 있습니다.

로 다시 작성 .apply했으므로 pd.Series또는로 전화 할 수 있습니다 pd.DataFrame.


파이썬 3 :

빈 문자열 또는 완전히 공백 인 문자열을 바꾸려면 :

df = df.apply(lambda x: np.nan if isinstance(x, str) and (x.isspace() or not x) else x)

전체 공백 문자열을 바꾸려면 :

df = df.apply(lambda x: np.nan if isinstance(x, str) and x.isspace() else x)

파이썬 2에서 이것을 사용하려면, 당신은 교체해야합니다 str함께 basestring.

파이썬 2 :

빈 문자열 또는 완전히 공백 인 문자열을 바꾸려면 :

df = df.apply(lambda x: np.nan if isinstance(x, basestring) and (x.isspace() or not x) else x)

전체 공백 문자열을 바꾸려면 :

df = df.apply(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)

1

이것은 나를 위해 일했습니다. csv 파일을 가져올 때 na_values ​​= ''를 추가했습니다. 공백은 기본 NaN 값에 포함되지 않습니다.

df = pd.read_csv (파일 경로, na_values ​​= '')


0

필터를 사용하여 수행 할 수도 있습니다.

df = PD.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'foo', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', '  '])
    df[df=='']='nan'
    df=df.astype(float)

이 코드의 모든 줄 (데이터 제외)에 결함이 있습니다.
Julius

0
print(df.isnull().sum()) # check numbers of null value in each column

modifiedDf=df.fillna("NaN") # Replace empty/null values with "NaN"

# modifiedDf = fd.dropna() # Remove rows with empty values

print(modifiedDf.isnull().sum()) # check numbers of null value in each column

0

이것은 우아한 해결책은 아니지만 작동하는 것처럼 보이는 것은 XLSX에 저장 한 다음 다시 가져 오는 것입니다. 이 페이지의 다른 솔루션은 효과가 없었습니다.

data.to_excel(filepath, index=False)
data = pd.read_excel(filepath)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.