Python/Pandas&Numpy

pandas Tricks_03 👉🏻 'Convert Strings→numbers ' (Kevin by DataSchool)

metamong 2022. 3. 25.

Q. 숱하게 많이 보이는 string형 data type...! 하지만 우리는 계산을 위해서 무조건 수치형으로 바꿔야 한다.. 하지만 너무 많은 방법들이 있다. 어떤게 제일 효과적이고 좋은 방법일까? 이 포스팅으로 한 방에 해결하자..!

 

A. 👉🏻 to_numeric 

 

먼저 string type의 수를 모두 입력 (한 개는 -)

 

df = pd.DataFrame({'col_one':['1.1','2.2','3.3'],
                   'col_two':['4.4','5.5','6.6'],
                   'col_three':['7,7','8.8','-']})

 


1. astype()

♠astype() docu - https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.astype.html 

 

DataFrame.astype(dtype, copy=True, errors='raise')

 

** dtype explanation **

"Use a numpy.dtype or Python type to cast entire pandas object to the same type. Alternatively, use {col: dtype, …}, where col is a column label and dtype is a numpy.dtype or Python type to cast one or more of the DataFrame’s columns to column-specific types."

 

→ astype()은 매우 좋은 데이터프레임 method. 하지만, 모든 dtype이 astype()에 의해 원하는 type으로 변경되지는 않는다.

- astype()은 원하는 column, 아니면 데이터프레임 전체의 dtype을 바꿔 줄 수 있지만, 예를 들어 object형의 경우 float형으로 강제 변환이 가능하지 않듯이 변경하려는 data의 dtype을 먼저 확인해줘야 하는 단점이 있다.

- (하지만 int형과 같이 내가 확실히 dtype을 아는 column이라면 주저없이 astype 사용하면 OK!)

 

→ ex) object형인 col_three는 (- data때문) ValueError를 일으킨다

 

df.astype({'col_one':'float','col_two':'float','col_three':'float'}).dtypes
#ValueError: could not convert string to float: '7,7'

 

→ ex) 변환 가능한 첫, 두번째 column만 astype() 사용 결과 성공!

 

df.astype({'col_one':'float','col_two':'float'}).dtypes

''
col_one      float64
col_two      float64
col_three     object
dtype: object
'''

2. int()

♠ int() docu - https://docs.python.org/3/library/functions.html#int 

 

→ int()형은 정말 비추. 단순히 인자 문자열 한 개만 int 정수형으로 변환해 준다.

- 즉, 대용량 data를 다루는 dataframe 자체 & dataframe column 단위로는 변경 불가

- 'cannot convert the series to <class 'int'> 에러 발생: 즉, series & df 단위는 int() 쓰지 말라는 뜻

 

→ ex) 에러 발생

 

int(df['col_one'])
#TypeError: cannot convert the series to <class 'int'>

 

→ ex) 굳이 굳이 굳이.. 나는 꼭 int함수를 쓰고 싶다! 하면 for문 돌리면 된다.. (근데 누가 이렇게 귀찮게..ㅎ 걍 다른 함수 쓰자.)

 

for a in df['col_one']:
    print(float(a))
    
# 1.1 2.2 3.3

3. to_numeric()

♠ to_numeric docu - https://pandas.pydata.org/docs/reference/api/pandas.to_numeric.html 

 

= "Convert argument to a numeric type. The default return dtype is float64 or int64 depending on the data supplied. Use the downcast parameter to obtain other dtypes. Please note that precision loss may occur if really large numbers are passed in(이 정도로 엄~청 작거나 큰 수는 권장 x). Due to the internal limitations of ndarray, if numbers smaller than -9223372036854775808 (np.iinfo(np.int64).min) or larger than 18446744073709551615 (np.iinfo(np.uint64).max) are passed in, it is very likely they will be converted to float so that they can stored in an ndarray. These warnings apply similarly to Series since it internally leverages ndarray."

 

pandas.to_numeric(arg, errors='raise', downcast=None)

 

- arg) scalar, list, tuple, 1-d array, or Series (즉 데이터프레임 전체 빼고는 모든 형태 집어넣을 수 있음)

- errors) errors='coerce'의 경우 에러 발생하는 경우 모두 NaN 처리 / errors='ignore'하면 input 형태 그대로 처리

 

→ ex) fillna()를 추가하여 coerce 값으로 처리한 NaN 결과를 원하는 결과로 채울 수 있음

 

pd.to_numeric(df.col_three,errors='coerce')

'''
0    7.7
1    8.8
2    NaN
Name: col_three, dtype: float64
'''

pd.to_numeric(df.col_three,errors='coerce').fillna(0)

 

(추가 Q) 그렇다면 to_numeric으로 전체 dataframe dtype을 못바꾸는데 모든 column 한번에 바꾸는 방법?

A. apply() method 활용

 

♠apply() docu - https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.apply.html 

 

= "Apply a function along an axis of the DataFrame. Objects passed to the function are Series objects whose index is either the DataFrame’s index (axis=0) or the DataFrame’s columns (axis=1). By default (result_type=None), the final return type is inferred from the return type of the applied function. Otherwise, it depends on the result_type argument.

 

DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwargs)

 

- axis=0이면 한 column 단위로 func을 적용하겠다는 소리 / axis=1이면 한 row 단위로 적용

- 그 외 인자도 많지만 일단 여기까지만..!

 

→ 그래서 앞서 적용했던 to_numeric function을 apply에 적용하면 한 번에 수치형 변수로 전환이 가능..!

 

df.apply(pd.to_numeric, errors='coerce').fillna(0).dtypes

'''
col_one      float64
col_two      float64
col_three    float64
dtype: object
'''

 

- 한 줄로 끝 😃 -


↓ apply 관련 자세한 포스팅 하단 참조 ↓

(map applymap 포스팅)

 

 

*출처 youtube) https://youtu.be/RlIiVeig3hc

댓글