빅데이터 분석기사/작업 유형 1 (pd)

평균을 사용한 결측치 대체

유방울 2023. 5. 16. 18:54

측정일시별 미세먼지별 평균

way 1 df.groupby('칼럼')['칼럼'].agg(['mean'])

way 2 df.groupby('칼럼')['칼럼'].mean()

-> 인덱스 바뀜

# 측정일시별 미세먼지별로 평균
# way 1
df_dust.groupby('측정일시')['미세먼지(㎍/㎥)'].agg(['mean'])

# way2
df_dust.groupby('측정일시')['미세먼지(㎍/㎥)'].mean()

측정일시
20160101    70.736842
20160102    53.789474
20160103    98.861111
20160104    76.205128
20160105    34.333333
              ...    
20200814    31.660000
20200815    37.400000
20200816    22.380000
20200817    24.980000
20200818    27.080000
Name: 미세먼지(㎍/㎥), Length: 1403, dtype: float64

way3 df.groupby('칼럼')['칼럼'].transform('mean') -> 인덱스 변경 안됨

# transfor() 인덱스 변경 안됨
fine_dust = df_dust.groupby('측정일시')['미세먼지(㎍/㎥)'].transform('mean')
fine_dust

0        70.736842
1        70.736842
2        70.736842
3        70.736842
4        70.736842
           ...    
60203    27.080000
60204    27.080000
60205    27.080000
60206    27.080000
60207    27.080000
Name: 미세먼지(㎍/㎥), Length: 60208, dtype: float64

결측치 값 개수 구함 

튜플로 나타남 

# [3-40] df_dust['미세먼지(㎍/㎥)'], fine_dust의 결측치 값의 개수를 구합니다.
df_dust['미세먼지(㎍/㎥)'].isna().sum(), fine_dust.isna().sum()

(881, 0)

 

way 1

df['칼럼'] = df['칼럼'].mask(df['칼럼'].isna(), df2) : df['칼럼']이 결측치인 행을 df2로 채우기

mask()

# [3-41] df_dust의 '미세먼지(㎍/㎥)'의 결측치를 fine_dust의 값으로 채우기 합니다.
# 채우기 한 결과를 다시 df_dust['미세먼지(㎍/㎥)']로 저장합니다.
# way 1
df_dust['미세먼지(㎍/㎥)'] = df_dust['미세먼지(㎍/㎥)'].mask(df_dust['미세먼지(㎍/㎥)'].isna(),fine_dust)

way2 

s = df['칼럼']

df['칼럼'] = s.mask(df['칼럼'].isna(), df2) : df['칼럼']

# way2 더 간략한 표현
s = df_dust['미세먼지(㎍/㎥)']
df_dust['미세먼지(㎍/㎥)'] = s.mask(df_dust['미세먼지(㎍/㎥)'].isna(),fine_dust)

비교를 위한 칼럼 추가

# [3-43] meandf에 '결측치대체' 및 '차이2'라는 컬럼을 추가합니다.
# '결측치대체' 컬럼은 df_dust에서 '년', '월'별 '미세먼지(㎍/㎥)' 데이터의 평균을 사용합니다.
# '차이2' 컬럼은 '미세먼지(㎍/㎥)' - '결측치대체'를 사용합니다.
meandf['결측치대체'] = df_dust.groupby(['년', '월'])['미세먼지(㎍/㎥)'].mean()
meandf['차이2'] = meandf['미세먼지(㎍/㎥)'] - meandf['결측치대체']
meandf

		미세먼지(㎍/㎥)	결측치제거후	차이	결측치대체	차이2
년	월					
2016	1	52.693844	52.693844	0.000000	52.752104	-0.058261
		2	48.283273	48.283273	0.000000	48.293733	-0.010460
		3	66.799503	66.799503	0.000000	66.850594	-0.051091
		4	73.327039	73.327039	0.000000	73.478543	-0.151504
		5	58.624172	58.571784	0.052388	58.610857	0.013315
		6	47.872304	47.872304	0.000000	47.777946	0.094358
		7	35.531092	35.417235	0.113857	35.423542	0.107550
		8	37.124378	37.147870	-0.023492	37.107287	0.017091

차이의 절댓값한 후 합계 구해서 비교

차이2가 더 작은 수치 -> 평균값 대체 채택

# 차이와 차이2의 합계를 구해서 비교하기
# 음수와 양수가 섞여있기 때문에 절댓값으로 보기
meandf['차이'].abs().sum(), meandf['차이2'].abs().sum()

(7.062269281823493, 2.76528301020522)

대체하기!

way 1 3개 칼럼 대체 -> 3번 반복 일일히

# [3-45] df_dust의 '오존농도(ppm)', '초미세먼지(㎍/㎥)' 컬럼에 대해서도
# '미세먼지(㎍/㎥)'와 같이 동일한 '년', '월', '일'의 평균 값으로 채우기 합니다.
# way 1 같은 것응ㄹ 3번 똑같이 칼럼명만 바꾸기
fine_dust = df_dust.groupby('측정일시')['오존농도(ppm)'].transform('mean')
s = df_dust['오존농도(ppm)']
df_dust['오존농도(ppm)'].mask(df_dust['오존농도(ppm)'].isna(),fine_dust)

way2 3번 반복을 for문 사용하기 -> 이 정도로 익숙해지기

# 같은 것을 3번 작업해야 함 -> 반복문 사용하기
# 대상을 목록으로 주기
for t in ['오존농도(ppm)', '초미세먼지(㎍/㎥)']:
    x = df_dust.groupby('측정일시')[t].transform('mean')
    s = df_dust[t]
    df_dust[t] = s.mask(df_dust[t].isna(),x)

파일 저장

-> 똑같이 결측치 없음

# 필요시 저장하였다가 가져와 사용하면 됩니다 ^^!
df_dust.to_csv('fine_dust02.csv', index=False)

df_dust2 = pd.read_csv('fine_dust02.csv')
df_dust2.isna().sum()

객체 저장

-> 똑같이 결측치 없음

# 객체로 저장하는 게 좋음
import shelve
with shelve.open('mydata') as data:
    data['fine_data02'] = df_dust
    
import shelve
with shelve.open('mydata') as data:
    df_dust3 = data['fine_data02']