본문 바로가기
개발일지/Pandas

pandas 판다스 틀린부분 복기 7 데이터 정리하기

by 다니엘의 개발 이야기 2022. 8. 1.
320x100

와.... 이번 파트는 호흡도 길었지만 정말 어려웠다.

정말 뭔가가 난해했다.

익숙해지면 크게 어려울 것은 아닌것같은데 역시나 '익숙하지 않다는것' 아직은!!

 

진짜 속수무책으로 당해버렸다. 거의 문제의 60%는 정답에 의지했던 것같다.

 

# 기본 배경 값

# run the cell!
cars.head(20)

'''
    mpg	cylinders	displacement	horsepower	weight	acceleration	model year	origin	name
0	18.0	8	307.0	130.0 hp	3504	12.0	70	United States	chevrolet chevelle malibu
1	15.0	8	350.0	165.0 hp	3693	11.5	70	United States	buick skylark 320
2	18.0	8	318.0	150.0 hp	3436	11.0	70	United States	plymouth satellite
3	16.0	8	304.0	150.0 hp	3433	12.0	70	usa	amc rebel sst
4	17.0	8	302.0	140.0 hp	3449	10.5	70	usa	FORD TORINO
5	15.0	8	429.0	198.0 hp	4341	10.0	70	usa	FORD GALAXIE 500
'''
# run the cell! 
cars.info()

'''
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 329 entries, 0 to 328
Data columns (total 9 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   mpg           329 non-null    float64
 1   cylinders     329 non-null    int64  
 2   displacement  329 non-null    float64
 3   horsepower    329 non-null    object 
 4   weight        329 non-null    int64  
 5   acceleration  329 non-null    float64
 6   model year    329 non-null    int64  
 7   origin        329 non-null    object 
 8   name          329 non-null    object 
dtypes: float64(3), int64(3), object(3)
memory usage: 23.3+ KB
'''


# 문제1. Apply the appropriate string operation to remove "hp" from the horsepower column! Pay attention to whitespaces! Overwrite the horsepower column!

# sql의 정규표현식처럼 일정 자리 뒷자리에 있는것를 제거해주는 방법을 잊어먹었다.
# 더불어서 replace로 시도해 봤는데, 먹히지가 않는다.

# cars.horsepower.replace(to_replace=' hp', value = '')

# replace 이전에 str을 해주는 것이 핵심이였다.
cars.horsepower = cars.horsepower.str.replace(' hp','')
cars.horsepower[0]
# 문제2. Create "real" missing values in the column horsepower! Save the change! Fill in the gaps!

# missing values를 Not available 대신에 이용하라고 하여서
# 바꾸었고
# 이게 내 코드였다. 하지만 출제자의 의도는 이런 느낌의 결측치가 아니라. 말 그대로 의도적 결측치를 만들라는 것이였다.
# 음.. 똑같은말 같긴한데 아무튼..
# cars.horsepower.replace("Not available", 'missing values', inplace = True)

# 정답코드
cars.horsepower.replace('Not available', np.nan, inplace = True)

# NaN값은 중간에 껴있더라도 data type을 변경하는 것이 가능하다.
# 문제 3. Now you can convert the datatype in the column horsepower! Overwrite the column!

# 당연하겠지만, 타입변경에 있어서 에러가 났다.
cars.horsepower = cars.horsepower.astype('float')

# ValueError: could not convert string to float: 'missing values'
# 문제4. Convert all names to lowercase and remove all whitespaces on the left ends and right ends! Overwrite!

cars.name = cars.name.str.split()
cars.name
# 이게 내 코드였는데, 결과적으로 옳은것같이 보였으나
# cars.name.str.lower()
# 전체가 다 리스트 형태였고
# 이를 lower()를 먹여주는 순간, 전체값이 NaN이 되었다.

cars.name = cars.name.str.lower().str.strip()
cars.name

# 이렇게 하니깐 리스트 형태가 아니게 되었다.

'''
0              chevrolet chevelle malibu
1                      buick skylark 320
2                     plymouth satellite
3                          amc rebel sst
4                            ford torino
5                       ford galaxie 500
6                       chevrolet impala
7                      plymouth fury iii
'''
# 문제 5. Select the complete row of the outlier with the method idxmax()!

# 이건 아예 생각도 못하겠다. idxmax()?

# 이렇게 하면 최고값이 들어있는 인덱스를 리턴해준다.
# cars.weight.idxmax()
cars.loc[cars.weight.idxmax()]

'''
mpg                   26.0
cylinders                4
displacement          97.0
horsepower            78.0
weight               23000
acceleration          14.5
model_year              74
origin              europe
name            opel manta
Name: 126, dtype: object
'''
# 문제6. Overwrite the erroneous outlier! Fill in the gaps!

# 컴머로 구분되어있어서 잘 모르겠더라;

cars.loc[cars.weight.idxmax(), 'weight'] = 2300

# 먼저는 전체적인 인덱스가 될 것을 지정해주고, 그 다음엔 그 인덱스 안에 들어있는 칼럼을 따로 빼주기
# 문제7. After some research we have found out that this extreme value is in "gallons per mile" units instead of "miles per gallon".
# Convert to "miles per gallon" units! Fill in the gaps!

# 음... 이건 이해하기가 난해하다.
# 분자 / 분모가 되어야 하는데
# 분모 / 분자가 된 상황이니깐 이걸 해결하라. 같은데..

cars.loc[cars.mpg.idxmin(),'mpg'] = 1/cars.loc[cars.mpg.idxmin(), 'mpg']

# 답을 보고 나서도 이해가 난해하다.
# =의 앞에 있는건 오케이 설명이 필요없다.
# 그런데 왜 1/오류값을 함으로 올바른 값으로 되었을까?
# 원리가 뭘까?
# 문제 8. Next, select all rows with at least one missing/na value! Fill in the gaps!

# **** 중요 *****
# 와.. 이것도 속수무책이다.
# 전혀 감도 안잡혔었다.

cars.loc[cars.isna().any(axis = 1)]

'''
	mpg	cylinders	displacement	horsepower	weight	acceleration	model_year	origin	name
28	25.0	4	98.0	NaN	2046	19.0	71	usa	ford pinto
111	21.0	6	200.0	NaN	2875	17.0	74	usa	ford maverick
276	40.9	4	85.0	NaN	1835	17.3	80	europe	renault lecar deluxe
279	23.6	4	140.0	NaN	2905	14.3	80	usa	ford mustang cobra
290	34.5	4	100.0	NaN	2320	15.8	81	europe	renault 18i
'''
# 문제9. As horsepower is an important feature in the cars dataset, we decide to remove all 6 rows. Remove and save the change!

# cars.drop?
# cars.remove?
# 어떻게 하는 거였더라.
# 내 코드고
# cars.loc[cars.isna().any(axis = 1)]

# 정답 코드다.
cars.dropna(inplace=True)
# 이 코드 정말 유용한 것 같다.
cars[cars.isna().any(axis = 1)]

# 컬럼을 기준으로 결측치가 있는 행을 출력한다니.
# 아무튼 더이상 나오는 값은 없다.
# 문제10. The first naive assumption is that two cars cannot have the same name. Let´s count the number of name-duplicates. Fill in the gaps!

# 음.. 이것도 어렵네?
# 내 코드
# cars.duplicated('name' = []).sum()

# 정답코드
cars.duplicated(subset= 'name').sum()

# 진짜 정답코드는
# cars.duplicated(subset= ['name']).sum() 였다.
# 굳이 대괄호 안에 넣어줄 필요가 있었을까?
# 문제11. Let´s inspect the duplicated pairs by selecting all instances of a name duplicate! Fill in the gaps!
# Should the name be the only criteria to identify duplicates?

# 추측을 해보자.
# 공통된 중복 값을 구해주려고 한다. - duplicated
# 중복값을 구할때 기준은 name이라는 컬럼을 기준으로 하자. - subset = ['name']
# 중복된 값이 포함된 행의 전체값을 생략없이 출력해주자. - keep = False
# 최종 정리는 'name'컬럼안의 필드를 기준으로 해주자 - sort_values('name')

cars.loc[cars.duplicated(subset = ['name'], keep = False)].sort_values("name")

# 이게 맞을까? 얼추 맞을 것은 같지만 영어 디스크립션 해독이 어렵네... ㅠㅠㅠ
# 문제12. To be on the safe side, let´s include all columns to identify duplicates. Count the number of duplicates! Fill in the gaps!

# 이거는 맞았는데 얻어걸린것 같은 느낌이다.

cars.duplicated().sum()
# 문제 13. Let´s inspect the __duplicated pairs__ by selecting __all instances__ of a duplicate! __Fill in the gaps__!

# 내코드
# 근데 이것도 작성이 거의 다 되어있어서 얻어걸린 느낌이다.

# cars.loc[cars.duplicated()].sort_values("name")
# 뭐.. 결과적으론 정답과 차이가 있다.
# 이렇게 하면 중복값이 포함되어있는 행 중에서 각 한개씩만 출력된다.

cars.loc[cars.duplicated(keep = False)].sort_values('name')
# 하지만 이렇게 해주면 중복되는 필드가 속해있는 모든 행이 다 출력된다.
# 문제14. Drop one instance of each duplicated pair! Save the change!

# 오... 이것도 생각도 못했었다.

cars.drop_duplicates(inplace = True)
# 문제 15. Our dataset seems to be pretty clean now! Save and export to a new csv-file (cars_clean.csv)! Do not export the RangeIndex!

cars.to_csv('cars_clean.csv', index = False)
# Call the describe() method on all non-numerical columns!

# run the cell!
cars.describe(include = "O")

# 이것도 샘플이 없었다면 생각도 못했을 것이다.
# 문제 16. Are there any categorical features (only few unique values) where the datatype could be converted to "category"?
#  If so, convert and overwrite the column(s)!

# 어... 질문은 이해했는데, 어떻게 확인하지?

# 정답코드
cars.origin = cars.origin.astype('category')

# category로 전환이 가능한 컬럼이 describe로 확인했을때 origin과 name이 나왔기에 2개의 컬럼 모두다 바꾸어 주는게
# 맞는거 아닌가?
# 근데 한편으로는 단서로 only few unique values라고 해주었으니 origin이 적합한것 같기도 하다.


재도전 하면서도 잘 모르겠는것들을 다시 적어봣다.

 

# 문제1. Convert all names to lowercase and remove all whitespaces on the left ends and right ends! Overwrite!

# split()으로 하면 전체가 리스트 화 되고
# strip()으로 하면 전체가 리스트 화 풀린 상태로 저장 된다.

# 더불어서 str.lower().str.strip()을 하든
# str.strip().str.lower()를 하든 순서는 중요하지 않다.
# 중요한 것은 strip으로 리스트화를 풀어주느냐, split으로 리스트화시키느냐가 중요하다.
# 리스트화 이후의 소문자등 변형 함수를 써주면 NaN값이 나오기 때문이다.

# cars.name.str.lower().str.strip()

cars.name = cars.name.str.strip().str.lower()
# 문제2. Overwrite the erroneous outlier! Fill in the gaps!

# 이부분은 굉장히 신기하다.

# 이렇게 수식을 썼을때, 조회는 되지만 오버라이드를 포함한 어떤 변경도 되지 않는다.
# cars[cars.weight.idxmax(), 'weight'] = 2300

# 오버라이드 등 변형을 기한다면 cars.loc을 써줘야하더라.
cars.loc[cars.weight.idxmax(), 'weight'] = 2300
# 문제3. The first naive assumption is that two cars cannot have the same name. Let´s count the number of name-duplicates. Fill in the gaps!

# 내 코드
# 이렇게하면 결과론적으로 어떤 칼럼들이 몇개가 있는지 확인은 가능하다.
# cars.loc[cars.name.duplicated()]

# 하지만 더 간결함을 원한다면 정답코드처럼 가야한다.
cars.duplicated(subset='name').sum()
# 86
# 문제4. Let´s inspect the duplicated pairs by selecting all instances of a name duplicate! Fill in the gaps!
# Should the name be the only criteria to identify duplicates?

# 이것도 아예 잊고 있었다.
# 문제가 뭔지도 이해가 잘 안갔다.

cars.loc[cars.duplicated(subset = 'name', keep = False)].sort_values('name')
# 문제5. Drop one instance of each duplicated pair! Save the change!

# 오... 이것도 생각도 못했었다.

cars.drop_duplicates(inplace = True)
300x250