이번 포스팅에서는 Python pandas DataFrame 이나 Series 내 문자열 칼럼을 숫자형으로 변환(how to convert string columns to numeric data types in pandas DataFrame, Series) 하는 2가지 방법을 소개하겠습니다. 


(1) pd.to_numeric() 함수를 이용한 문자열 칼럼의 숫자형 변환

(2) astype() 메소드를 이용한 문자열 칼럼의 숫자형 변환





  (1) pd.to_numeric() 함수를 이용한 문자열 칼럼의 숫자형 변환


(1-1) 한개의 문자열 칼럼을 숫자형으로 바꾸기



import numpy as np

import pandas as pd


# make a DataFrame

df = pd.DataFrame({'col_str': ['1', '2', '3', '4', '5']})

df

col_str
01
12
23
34
45


# check data types 

df.dtypes

col_str    object
dtype: object


df['col_int'] = pd.to_numeric(df['col_str'])

df

col_strcol_int
011
122
233
344
455


df.dtypes

col_str    object
col_int     int64
dtype: object





(1-2) apply() 함수와 to_numeric() 함수를 사용해 DataFrame 내 다수의 문자열 칼럼을 숫자형으로 바꾸기



# make a DataFrame with 3 string columns

df2 = pd.DataFrame({'col_str_1': ['1', '2', '3'], 

                   'col_str_2': ['4', '5', '6'], 

                   'col_str_3': ['7.0', '8.1', '9.2']})


df2

col_str_1col_str_2col_str_3
0147.0
1258.1
2369.2



df2.dtypes

col_str_1    object
col_str_2    object
col_str_3    object
dtype: object



# convert 'col_str_1' and 'col_str_2' to numeric

df2[['col_int_1', 'col_int_2']] = df2[['col_str_1', 'col_str_2']].apply(pd.to_numeric)

df2

col_str_1col_str_2col_str_3col_int_1col_int_2
0147.014
1258.125
2369.236



df2.dtypes

col_str_1    object
col_str_2    object
col_str_3    object
col_int_1     int64
col_int_2     int64
dtype: object



# convert all columns of a DataFrame to numeric using apply() and to_numeric together

df3 = df2.apply(pd.to_numeric)


df3.dtypes

col_str_1      int64
col_str_2      int64
col_str_3    float64
col_int_1      int64
col_int_2      int64
dtype: object






  (2) astype() 메소드를 이용한 문자열 칼럼의 숫자형 변환


(2-1) DataFrame 내 모든 문자열 칼럼을 float로 한꺼번에 변환하기



df4 = pd.DataFrame({'col_str_1': ['1', '2', '3'], 

                   'col_str_2': ['4.1', '5.5', '6.0']}) 


df4.dtypes

col_str_1    object
col_str_2    object
dtype: object



df5 = df4.astype(float)

df5

col_str_1col_str_2
01.04.1
12.05.5
23.06.0



df5.dtypes

col_str_1    float64
col_str_2    float64
dtype: object





(2-2) DataFrame 내 문자열 칼럼별로 int, float 데이터 형식 개별 지정해서 숫자형으로 변환하기



df6 = df4.astype({'col_str_1': int

                  'col_str_2': np.float})


df6

col_str_1col_str_2
014.1
125.5
236.0



 df6.dtypes

col_str_1      int64
col_str_2    float64
dtype: object






  DataFrame에 문자가 포함된 칼럼이 같이 있을 경우 ValueError


물론 DataFrame 내의 문자열 중에서 숫자가 아니라 문자(character)로 이루어진 문자열(string)이 포함되어 있을 경우 apply(pd.to_numeric) 함수나 DataFrame.astype(int) 메소드를 써서 한꺼번에 숫자형 데이터 형태로 변환하려고 하면 ValueError 가 발생합니다. (너무 당연한 거라서 여기에 써야 하나 싶기도 한데요... ^^;) 


이럴 때는 숫자만 들어있는 문자열 칼럼만을 선택해서 개별적으로 변환을 해주면 됩니다. 


아래는 문자로만 구성된 문자열 'col_2' 를 포함한 df7 데이터프레임을 만들어서 전체 칼럼을 숫자형으로 바꾸려고 했을 때 ValueError 가 발생한 예입니다. 



df7 = pd.DataFrame({'col_1': ['1', '2', '3'], 

                   'col_2': ['aaa', 'bbb', 'ccc']})


df7

col_1col_2
01aaa
12bbb
23ccc



df7.dtypes

col_1    object
col_2    object
dtype: object

 



* ValueError


 

# ValueError

df7 = df7.apply(pd.to_numeric)

--------------------------------------------------------------------------- ValueError Traceback (most recent call last) pandas/_libs/src/inference.pyx in pandas._libs.lib.maybe_convert_numeric() ValueError: Unable to parse string "aaa" During handling of the above exception, another exception occurred: -- 중간 생략 -- ~/anaconda3/lib/python3.6/site-packages/pandas/core/tools/numeric.py in to_numeric(arg, errors, downcast) 124 coerce_numeric = False if errors in ('ignore', 'raise') else True 125 values = lib.maybe_convert_numeric(values, set(), --> 126 coerce_numeric=coerce_numeric) 127 128 except Exception: pandas/_libs/src/inference.pyx in pandas._libs.lib.maybe_convert_numeric() ValueError: ('Unable to parse string "aaa" at position 0', 'occurred at index col_2')




* ValueError


# ValueError

df7 = df7.astype(int)

--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-124-f50dad302c83> in <module>() ----> 1 df7 = df7.astype(int) -- 중간 생략 --

~/anaconda3/lib/python3.6/site-packages/pandas/core/dtypes/cast.py in astype_nansafe(arr, dtype, copy) 623 elif arr.dtype == np.object_ and np.issubdtype(dtype.type, np.integer): 624 # work around NumPy brokenness, #1987 --> 625 return lib.astype_intsafe(arr.ravel(), dtype).reshape(arr.shape) 626 627 if dtype.name in ("datetime64", "timedelta64"): pandas/_libs/lib.pyx in pandas._libs.lib.astype_intsafe() pandas/_libs/src/util.pxd in util.set_value_at_unsafe()  

ValueError: invalid literal for int() with base 10: 'aaa' 





 문자열을 숫자형으로 변환 시 ValueError 를 무시하기: df.apply(pd.to_numeric, errors = 'coerce') 



위의 예와는 조금 다르게 문자형을 숫자형으로 변환하려는 칼럼이 맞는데요, 값 중에 몇 개가 실수로 숫자로 된 문자열이 아니라 문자로 된 문자열이 몇 개 포함되어 있다고 해봅시다. 이럴 경우 문자열을 숫자로 파싱할 수 없다면서 ValueError가 발생하는데요, 문자가 포함되어 있는 경우는 강제로 'NaN'으 값으로 변환하고, 나머지 숫자로된 문자열은 숫자형으로 변환해주려면 errors = 'coerce' 옵션을 추가해주면 됩니다. 


 

df8 = pd.DataFrame({'col_1': ['1', '2', '3'], 

                   'col_2': ['4', 'bbb', '6']})


df8

col_1col_2
014
12bbb
236



df8 = df8.apply(pd.to_numeric)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
pandas/_libs/src/inference.pyx in pandas._libs.lib.maybe_convert_numeric()

ValueError: Unable to parse string "bbb"

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-130-9e8d711c10d5> in <module>()
----> 1 df8 = df8.apply(pd.to_numeric)

~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in apply(self, func, axis, broadcast, raw, reduce, args, **kwds)
   4260                         f, axis,
   4261                         reduce=reduce,
-> 4262                         ignore_failures=ignore_failures)
   4263             else:
   4264                 return self._apply_broadcast(f, axis)

~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in _apply_standard(self, func, axis, ignore_failures, reduce)
   4356             try:
   4357                 for i, v in enumerate(series_gen):
-> 4358                     results[i] = func(v)
   4359                     keys.append(v.name)
   4360             except Exception as e:

~/anaconda3/lib/python3.6/site-packages/pandas/core/tools/numeric.py in to_numeric(arg, errors, downcast)
    124             coerce_numeric = False if errors in ('ignore', 'raise') else True
    125             values = lib.maybe_convert_numeric(values, set(),
--> 126                                                coerce_numeric=coerce_numeric)
    127 
    128     except Exception:

pandas/_libs/src/inference.pyx in pandas._libs.lib.maybe_convert_numeric()

ValueError: ('Unable to parse string "bbb" at position 1', 'occurred at index col_2')



df8 = df8.apply(pd.to_numeric, errors = 'coerce')

df8

col_1col_2
014.0
12NaN
236.0




많은 도움이 되었기를 바랍니다. 


이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요.  :-)



728x90
반응형
Posted by Rfriend
,