programing

Pandas DataFrame에서 빈 셀을 포함하는 행 삭제

randomtip 2021. 1. 17. 10:49
반응형

Pandas DataFrame에서 빈 셀을 포함하는 행 삭제


일부 Excel 스프레드 시트를 구문 분석하여 만든 pd.DataFrame이 있습니다. 빈 셀이있는 열입니다. 예를 들어 아래는 해당 열의 빈도에 대한 출력이며 32320 레코드에는 Tenant에 대한 누락 된 값이 있습니다.

   In [67]: value_counts(Tenant,normalize=False)
   Out[67]:
                              32320
   Thunderhead                8170
   Big Data Others            5700
   Cloud Cruiser              5700
   Partnerpedia               5700
   Comcast                    5700
   SDP                        5700
   Agora                      5700
   dtype: int64

Tenant가 누락 된 행을 삭제하려고하는데 isnull 옵션이 누락 된 값을 인식하지 못합니다.

   In [71]: df['Tenant'].isnull().sum()
   Out[71]: 0

열의 데이터 유형은 "개체"입니다. 이 경우 무슨 일이 일어나고 있습니까? 테넌트가 누락 된 레코드를 어떻게 삭제할 수 있습니까?


Pandas는 np.nan개체 인 경우 값을 null로 인식 NaN하고 DataFrame에서와 같이 인쇄 합니다. 누락 된 값은 팬더가 null로 인식하지 못하는 빈 문자열 일 수 있습니다. 이 문제를 해결 하려면를 np.nan사용하여 스팅 (또는 빈 셀에있는 모든 항목)을 개체 로 변환 replace()한 다음 dropna()DataFrame을 호출 하여 null 테넌트가있는 행을 삭제할 수 있습니다.

설명하기 위해 Tenants열에 임의의 값과 빈 문자열이있는 DataFrame을 만듭니다 .

>>> import pandas as pd
>>> import numpy as np
>>> 
>>> df = pd.DataFrame(np.random.randn(10, 2), columns=list('AB'))
>>> df['Tenant'] = np.random.choice(['Babar', 'Rataxes', ''], 10)
>>> print df

          A         B   Tenant
0 -0.588412 -1.179306    Babar
1 -0.008562  0.725239         
2  0.282146  0.421721  Rataxes
3  0.627611 -0.661126    Babar
4  0.805304 -0.834214         
5 -0.514568  1.890647    Babar
6 -1.188436  0.294792  Rataxes
7  1.471766 -0.267807    Babar
8 -1.730745  1.358165  Rataxes
9  0.066946  0.375640         

이제 Tenants열의 빈 문자열을 다음 np.nan같이 객체로 바꿉니다.

>>> df['Tenant'].replace('', np.nan, inplace=True)
>>> print df

          A         B   Tenant
0 -0.588412 -1.179306    Babar
1 -0.008562  0.725239      NaN
2  0.282146  0.421721  Rataxes
3  0.627611 -0.661126    Babar
4  0.805304 -0.834214      NaN
5 -0.514568  1.890647    Babar
6 -1.188436  0.294792  Rataxes
7  1.471766 -0.267807    Babar
8 -1.730745  1.358165  Rataxes
9  0.066946  0.375640      NaN

이제 null 값을 삭제할 수 있습니다.

>>> df.dropna(subset=['Tenant'], inplace=True)
>>> print df

          A         B   Tenant
0 -0.588412 -1.179306    Babar
2  0.282146  0.421721  Rataxes
3  0.627611 -0.661126    Babar
5 -0.514568  1.890647    Babar
6 -1.188436  0.294792  Rataxes
7  1.471766 -0.267807    Babar
8 -1.730745  1.358165  Rataxes

value_counts는 기본적으로 NaN을 생략하므로 ""를 처리 할 가능성이 높습니다.

따라서 다음과 같이 필터링 할 수 있습니다.

filter = df["Tenant"] != ""
dfNew = df[filter]

Pythonic + Pandorable : df[df['col'].astype(bool)]

빈 문자열은 거짓이므로 다음과 같이 bool 값을 필터링 할 수 있습니다.

df = pd.DataFrame({
    'A': range(5),
    'B': ['foo', '', 'bar', '', 'xyz']
})
df
   A    B
0  0  foo
1  1     
2  2  bar
3  3     
4  4  xyz

df['B'].astype(bool)                                                                                                                      
0     True
1    False
2     True
3    False
4     True
Name: B, dtype: bool

df[df['B'].astype(bool)]                                                                                                                  
   A    B
0  0  foo
2  2  bar
4  4  xyz

목표가 빈 문자열뿐만 아니라 공백 만 포함 된 문자열도 제거하는 것이라면 str.strip미리 다음을 사용하십시오 .

df[df['B'].str.strip().astype(bool)]
   A    B
0  0  foo
2  2  bar
4  4  xyz

생각보다 빠르게

.astype벡터화 된 연산이므로 지금까지 제시된 모든 옵션보다 빠릅니다. 적어도 내 테스트에서. YMMV.

여기에 타이밍 비교가 있습니다. 제가 생각할 수있는 다른 방법을 제시했습니다.

여기에 이미지 설명 입력

참조 용 벤치마킹 코드 :

import pandas as pd
import perfplot

df1 = pd.DataFrame({
    'A': range(5),
    'B': ['foo', '', 'bar', '', 'xyz']
})

perfplot.show(
    setup=lambda n: pd.concat([df1] * n, ignore_index=True),
    kernels=[
        lambda df: df[df['B'].astype(bool)],
        lambda df: df[df['B'] != ''],
        lambda df: df[df['B'].replace('', np.nan).notna()],  # optimized 1-col
        lambda df: df.replace({'B': {'': np.nan}}).dropna(subset=['B']),  
    ],
    labels=['astype', "!= ''", "replace + notna", "replace + dropna", ],
    n_range=[2**k for k in range(1, 15)],
    xlabel='N',
    logx=True,
    logy=True,
    equality_check=pd.DataFrame.equals)

셀에 공백이있는 상황이 있습니다. 볼 수 없습니다.

df['col'].replace('  ', np.nan, inplace=True)

공백을 NaN으로 바꾸려면

df= df.dropna(subset=['col'])

이 변형을 사용할 수 있습니다.

import pandas as pd
vals = {
    'name' : ['n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7'],
    'gender' : ['m', 'f', 'f', 'f',  'f', 'c', 'c'],
    'age' : [39, 12, 27, 13, 36, 29, 10],
    'education' : ['ma', None, 'school', None, 'ba', None, None]
}
df_vals = pd.DataFrame(vals) #converting dict to dataframe

다음과 같이 출력됩니다 (**-원하는 행만 강조 표시).

   age education gender name
0   39        ma      m   n1 **
1   12      None      f   n2    
2   27    school      f   n3 **
3   13      None      f   n4
4   36        ba      f   n5 **
5   29      None      c   n6
6   10      None      c   n7

따라서 '교육'값이없는 모든 항목을 삭제하려면 아래 코드를 사용하세요.

df_vals = df_vals[~df_vals['education'].isnull()] 

( '~'는 NOT을 나타냄)

결과:

   age education gender name
0   39        ma      m   n1
2   27    school      f   n3
4   36        ba      f   n5

참조 URL : https://stackoverflow.com/questions/29314033/drop-rows-tained-empty-cells-from-a-pandas-dataframe

반응형