파이썬 판다스 데이터프레임에서 NaN 이 아닌 값의 갯수를 세기 + 약간의 조건

조회수 388회

df에서 dd 인덱스 순서대로 NaN 제외한 열별로 value 개수 총합을 구하려고 하는데요

이전 df value값이 NaN이면 그 행은 제외하고 카운팅 되면 좋겠어요. 하드코딩한건 아래와 같습니다.
예시에선 4개 열뿐이지만 더 개수가 많아질 경우를 대비해서 lambda apply 써서 간단하게 하고 싶은데 어렵네요. 안된다면 for 문이라도요.

02 -> 5개(foo, fid, bar, cute, you)  
06 -> 4개(q, d, e, vd)  
07 -> 2개(g, z)  
08 -> 1개(a)  

[5, 4, 2, 1] 로 결과값이 나오면 좋겠는데 어떻게 해야하는지 모르겠네요 ..

import pandas as pd
import numpy as np

dd = {'02':1,'06':2,'07':3,'08':4}
dd = pd.DataFrame.from_dict(dd, orient = 'index', columns = ['step'])
print(dd)

left = pd.DataFrame({'02':['foo','fid','bar','cute'], '06':['q','d','e','vd']})
right = pd.DataFrame({'02':['foo','you','bar'],'07':['g','v','z'], '08':['a','b','c']})
df = pd.merge(left,right, on=['02'], how='outer')
df.iloc[2,3] = np.nan
print()
print(df)

df2 = df.loc[df['06'].notnull()]
df3 = df2.loc[df2['07'].notnull()]
df4 = df3.loc[df3['08'].notnull()]

a = df['02'].notnull().sum()
b = df2['06'].notnull().sum()
c = df3['07'].notnull().sum()
d = df4['08'].notnull().sum()

print()
print([a,b,c,d])

1 답변

    1. dataframe 전체에 대해 notnull() 을 해서 boolean 테이블을 만듭니다.
    2. 여기서 단순히 컬럼별로 na 가 아닌 데이터의 갯수를 새려면, df.sum(axis=0) 으로 충분합니다. 하지만 조건이 있습니다.
    3. 조건에 따라 컬럼명을 정렬하고,
    4. 연달아 나오는 컬럼명을 zip(cols[:-1], cols[1:]) 으로 두개씩 가져옵니다.
    5. 가져온 두컬럼에 대해서 순차적으로 논리적 AND 연산을 합니다.
    6. 연산후에 df.sum(axis=0) 으로 결과를 확인합니다.
    
    import pandas as pd
    import numpy as np
    
    dd = {"02": 1, "06": 2, "07": 3, "08": 4}
    dd_df = pd.DataFrame.from_dict(dd, orient="index", columns=["step"])
    print(dd_df)
    
    left = pd.DataFrame({"02": ["foo", "fid", "bar", "cute"], "06": ["q", "d", "e", "vd"]})
    right = pd.DataFrame({"02": ["foo", "you", "bar"], "07": ["g", "v", "z"], "08": ["a", "b", "c"]})
    df = pd.merge(left, right, on=["02"], how="outer")
    df.iloc[2, 3] = np.nan
    print()
    print(df)
    
    """
    df2 = df.loc[df['06'].notnull()]
    df3 = df2.loc[df2['07'].notnull()]
    df4 = df3.loc[df3['08'].notnull()]
    
    a = df['02'].notnull().sum()
    b = df2['06'].notnull().sum()
    c = df3['07'].notnull().sum()
    d = df4['08'].notnull().sum()
    
    print()
    print([a,b,c,d])
    """
    
    df = df.notnull()
    print(df)
    
    sorted_col = sorted(dd.keys(), key=lambda c: dd[c])
    # print(sorted_col)
    
    for col1, col2 in zip(sorted_col[:-1], sorted_col[1:]):
        df[col2] = df[col1] & df[col2]
        print(f"-- after ANDing {col1} and {col2} --")
        print(df)
    
    print(df.sum(axis=0))
    
    
    
        step
    02     1
    06     2
    07     3
    08     4
    
         02   06   07   08
    0   foo    q    g    a
    1   fid    d  NaN  NaN
    2   bar    e    z  NaN
    3  cute   vd  NaN  NaN
    4   you  NaN    v    b
         02     06     07     08
    0  True   True   True   True
    1  True   True  False  False
    2  True   True   True  False
    3  True   True  False  False
    4  True  False   True   True
    -- after ANDing 02 and 06 --
         02     06     07     08
    0  True   True   True   True
    1  True   True  False  False
    2  True   True   True  False
    3  True   True  False  False
    4  True  False   True   True
    -- after ANDing 06 and 07 --
         02     06     07     08
    0  True   True   True   True
    1  True   True  False  False
    2  True   True   True  False
    3  True   True  False  False
    4  True  False  False   True
    -- after ANDing 07 and 08 --
         02     06     07     08
    0  True   True   True   True
    1  True   True  False  False
    2  True   True   True  False
    3  True   True  False  False
    4  True  False  False  False
    02    5
    06    4
    07    2
    08    1
    dtype: int64
    
    
    • 와우! 이런 방법이 있었네요 감사합니다~ 땡큐베리너츠 2022.6.9 14:49

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)