Pandas에서 열의 데이터 유형 변경


804

목록 목록으로 표시된 테이블을로 변환하고 싶습니다 Pandas DataFrame. 매우 단순화 된 예로서 :

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a)

열을 적절한 유형으로 변환하는 가장 좋은 방법은 무엇입니까?이 경우 열 2와 3은 부동 소수점으로? DataFrame으로 변환하는 동안 유형을 지정하는 방법이 있습니까? 아니면 먼저 DataFrame을 만든 다음 열을 반복하여 각 열의 유형을 변경하는 것이 더 낫습니까? 수백 개의 열이있을 수 있고 어떤 유형의 열을 정확하게 지정하고 싶지 않기 때문에 이상적으로 동적 방식 으로이 작업을 수행하고 싶습니다. 보장 할 수있는 것은 각 열에 동일한 유형의 값이 포함되어 있다는 것입니다.


모든 열을 변환하는 방법과 특별히 명명 된 열을 변환하는 방법을 보았지만 한 번에 변환하려는 100 개의 열을 나열 할 수없는 경우 특정 조건을 충족하는 특정 열은 어떻습니까? 모든 float64-> float32 또는 기타 메모리 절약 전술을 생각하고 있습니다.
demongolem

@demongolem : df.apply(pd.to_numeric, downcast="integer", errors="ignore")정수 열을 값을 보유하는 가장 작은 (정수) dtype으로 다운 캐스트 하는 것과 같은 작업을 수행 할 수 있습니다.
Alex Riley

답변:


1190

팬더에서 유형을 변환하기위한 세 가지 주요 옵션이 있습니다.

  1. to_numeric()-숫자가 아닌 유형 (예 : 문자열)을 적합한 숫자 유형으로 안전하게 변환하는 기능을 제공합니다. ( to_datetime()및 참조 to_timedelta())

  2. astype()-반드시 (거의) 모든 유형을 (거의) 다른 유형으로 변환하십시오 (필수적으로 합리적이지 않더라도). 또한 범주 유형 으로 변환 할 있습니다 (매우 유용).

  3. infer_objects() -가능하면 파이썬 객체를 보유한 객체 열을 팬더 유형으로 변환하는 유틸리티 메소드.

이러한 각 방법에 대한 자세한 설명과 사용법을 읽으십시오.


1. to_numeric()

DataFrame의 하나 이상의 열을 숫자 값으로 변환하는 가장 좋은 방법은을 사용하는 것 pandas.to_numeric()입니다.

이 함수는 숫자가 아닌 객체 (예 : 문자열)를 정수 또는 부동 소수점 숫자로 적절하게 변경하려고 시도합니다.

기본 사용법

입력 to_numeric()은 시리즈 또는 DataFrame의 단일 열입니다.

>>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
>>> s
0      8
1      6
2    7.5
3      3
4    0.9
dtype: object

>>> pd.to_numeric(s) # convert everything to float values
0    8.0
1    6.0
2    7.5
3    3.0
4    0.9
dtype: float64

보시다시피, 새 시리즈가 반환됩니다. 계속 사용하려면이 출력을 변수 또는 열 이름에 할당해야합니다.

# convert Series
my_series = pd.to_numeric(my_series)

# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])

또한 apply()메소드 를 통해 DataFrame의 여러 열을 변환하는 데 사용할 수 있습니다 .

# convert all columns of DataFrame
df = df.apply(pd.to_numeric) # convert all columns of DataFrame

# convert just columns "a" and "b"
df[["a", "b"]] = df[["a", "b"]].apply(pd.to_numeric)

값을 모두 변환 할 수있는 한 필요한 것입니다.

오류 처리

그러나 일부 값을 숫자 유형으로 변환 할 수 없으면 어떻게됩니까?

to_numeric()또한 errors숫자가 아닌 값을 강제로 NaN또는 키워드가 포함 된 열을 무시 하도록 하는 키워드 인수를 사용 합니다.

다음 s은 dtype 객체가 있는 일련의 문자열 을 사용하는 예입니다 .

>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0         1
1         2
2       4.7
3    pandas
4        10
dtype: object

기본 동작은 값을 변환 할 수없는 경우 올리는 것입니다. 이 경우 문자열 'pandas'에 대처할 수 없습니다.

>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string

실패하기보다는 '팬더'가 누락되거나 잘못된 숫자 값으로 간주되기를 원할 수 있습니다. 키워드 인수를 NaN사용하여 유효하지 않은 값을 다음과 같이 강제 변환 할 수 있습니다 errors.

>>> pd.to_numeric(s, errors='coerce')
0     1.0
1     2.0
2     4.7
3     NaN
4    10.0
dtype: float64

세 번째 옵션 errors은 유효하지 않은 값이 발견되면 작업을 무시하는 것입니다.

>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched

이 마지막 옵션은 전체 DataFrame을 변환하려고 할 때 특히 유용하지만 어떤 열을 숫자 유형으로 안정적으로 변환 할 수 있는지 모릅니다. 이 경우 다음과 같이 작성하십시오.

df.apply(pd.to_numeric, errors='ignore')

이 함수는 DataFrame의 각 열에 적용됩니다. 숫자 형식으로 변환 할 수있는 열은 변환되지만 숫자가 아닌 문자열이나 날짜를 포함 할 수없는 열은 그대로 유지됩니다.

다운 캐스팅

기본적으로로 변환 to_numeric()하면 a int64또는 float64dtype (또는 플랫폼에 고유 한 정수 너비)이 제공됩니다.

즉 당신이 원하는 일반적으로,하지만 당신이 더 컴팩트 DTYPE, 같은 일부 메모리를 저장하고 사용하기를 원한다면 float32, 또는 int8?

to_numeric()'정수', '서명 된', '서명되지 않은', '부동'으로 다운 캐스트 할 수있는 옵션을 제공합니다. 다음은 간단한 일련 s의 정수 유형에 대한 예입니다 .

>>> s = pd.Series([1, 2, -7])
>>> s
0    1
1    2
2   -7
dtype: int64

'정수'로 다운 캐스팅하면 값을 보유 할 수있는 가장 작은 정수를 사용합니다.

>>> pd.to_numeric(s, downcast='integer')
0    1
1    2
2   -7
dtype: int8

'float'로 다운 캐스팅 할 때와 마찬가지로 일반 부동 유형보다 작은 것을 선택합니다.

>>> pd.to_numeric(s, downcast='float')
0    1.0
1    2.0
2   -7.0
dtype: float32

2. astype()

astype()방법을 사용하면 DataFrame 또는 Series에 원하는 dtype을 명시 적으로 지정할 수 있습니다. 한 유형에서 다른 유형으로 시도하고 이동할 수 있다는 점에서 매우 다양합니다.

기본 사용법

유형을 선택하기 만하면 NumPy dtype (예 :) np.int16, 일부 Python 유형 (예 : bool) 또는 팬더 관련 유형 (예 : 범주 형 dtype)을 사용할 수 있습니다.

변환하려는 객체에서 메소드를 호출하면 자동으로 변환 astype()됩니다.

# convert all DataFrame columns to the int64 dtype
df = df.astype(int)

# convert column "a" to int64 dtype and "b" to complex type
df = df.astype({"a": int, "b": complex})

# convert Series to float16 type
s = s.astype(np.float16)

# convert Series to Python strings
s = s.astype(str)

# convert Series to categorical type - see docs for more details
s = s.astype('category')

주의 사항 "시도"라고 astype()말하면 Series 또는 DataFrame에서 값을 변환하는 방법을 모르면 오류가 발생합니다. 예를 들어 NaN또는 inf값이 있으면 정수로 변환하려고하면 오류가 발생합니다.

팬더 0.20.0부터는이 오류를 전달하여 억제 할 수 있습니다 errors='ignore'. 원래 개체는 그대로 유지됩니다.

조심해

astype()강력하지만 때때로 "잘못된"값을 변환합니다. 예를 들면 다음과 같습니다.

>>> s = pd.Series([1, 2, -7])
>>> s
0    1
1    2
2   -7
dtype: int64

이들은 작은 정수이므로 부호없는 8 비트 유형으로 변환하여 메모리를 절약하는 것은 어떻습니까?

>>> s.astype(np.uint8)
0      1
1      2
2    249
dtype: uint8

변환은 일을하지만,이 -7 249이 될 라운드 포장 된 (즉, 2 (8) - 7)!

pd.to_numeric(s, downcast='unsigned')대신 사용하여 다운 캐스트를 시도 하면이 오류를 방지하는 데 도움이 될 수 있습니다.


삼. infer_objects()

pandas 버전 0.21.0 infer_objects()에는 객체 데이터 유형이있는 DataFrame의 열을보다 구체적인 유형 (소프트 변환)으로 변환 하는 방법이 도입되었습니다 .

예를 들어 다음은 두 개의 객체 유형 열이있는 DataFrame입니다. 하나는 실제 정수를 보유하고 다른 하나는 정수를 나타내는 문자열을 보유합니다.

>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a    object
b    object
dtype: object

을 사용하여 infer_objects()열 'a'의 유형을 int64로 변경할 수 있습니다.

>>> df = df.infer_objects()
>>> df.dtypes
a     int64
b    object
dtype: object

'b'열은 값이 정수가 아닌 문자열이므로 단독으로 남겨졌습니다. 두 열을 정수 유형으로 강제 변환하려고하면 df.astype(int)대신 사용할 수 있습니다 .


8
또한 .astype (float)과는 달리 오류를 발생시키는 대신 문자열을 NaN으로 변환합니다
Rob

11
.convert_objects그 이후로 0.17사용 이 중단되었습니다 – df.to_numeric대신 사용
Matti Lyra

4
감사합니다-이 답변을 업데이트해야합니다. 주목할만한 가치가 pd.to_numeric있으며 동반 메서드는 달리 한 번에 하나의 열에서만 작동합니다 convert_objects. API의 대체 기능에 대한 논의가 진행중인 것 같습니다 . 전체 DataFrame에서 작동하는 메소드가 매우 유용하기 때문에 남아 있기를 바랍니다.
Alex Riley

현재 모든 열 int64int32? 로 변환하는 가장 좋은 방법은 무엇입니까 ?
RoyalTS

4
@RoyalTS : 아마도 astype다른 답변과 같이 사용하는 것이 가장 좋습니다 .astype(numpy.int32).
Alex Riley

447

이건 어때요?

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
df
Out[16]: 
  one  two three
0   a  1.2   4.2
1   b   70  0.03
2   x    5     0

df.dtypes
Out[17]: 
one      object
two      object
three    object

df[['two', 'three']] = df[['two', 'three']].astype(float)

df.dtypes
Out[19]: 
one       object
two      float64
three    float64

10
예! 찾고있는 / 할 수 pd.DataFrame있는 dtype논쟁이 있습니다. df = pd.DataFrame (a, columns = [ 'one', 'two', 'three'], dtype = float) [2]에서 : df.dtypes Out [2] : 하나의 객체 2 float64 3 float64 dtype : 객체
hernamesbarbara

17
제안대로 시도하면 경고 메시지가 나타납니다 SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead. 이것은 최신 버전의 팬더에서 도입되었을 수 있으며 결과적으로 잘못된 것을 보지 못하지만이 경고가 무엇인지 궁금합니다. 어떤 생각?
주황색

2
@orange 경고는 연결된 작업과 팬더가 데이터 프레임을 편집하지 않고 복사본을 반환하는 것과 혼동 될 수 있음을 사용자에게 경고하는 것입니다. stackoverflow.com/questions/20625582/… 및 관련 항목을 참조하십시오 .
A.Wan

19
좋은 방법이지만 열에 NaN이 있으면 작동하지 않습니다. float를 int로 캐스팅 할 때 NaN이 NaN을 유지할 수없는 이유를 ValueError: Cannot convert NA to integer
모릅니다

7
사전에 @GillBates 예. df = pd.DataFrame(a, columns=['one', 'two', 'three'], dtype={'one': str, 'two': int, 'three': float}). 허용되는 "dtype"값에 대한 사양을 찾는 데 어려움을 겪고 있습니다. 목록은 좋을 것입니다 (현재는 할 것입니다 dict(enumerate(my_list))).
FichteFoll

39

아래 코드는 열의 데이터 유형을 변경합니다.

df[['col.name1', 'col.name2'...]] = df[['col.name1', 'col.name2'..]].astype('data_type')

데이터 유형 대신에 데이터 유형을 제공 할 수 있습니다. str, float, int 등과 같은 것을 원하십니까?


data_type을 사용하여 문자열``` 'True'```및``` 'False'```를 포함하는 열에 이것을 적용하면 bool모든 것이로 변경됩니다 True.
H. Vabri

당신은 또한 "카테고리"를 입력 변환 할 수 있습니다이 옵션은
네 베스

17

특정 열만 지정하고 명시 적으로 표현하고 싶을 때 ( DOCS LOCATION 당 ) 사용했습니다.

dataframe = dataframe.astype({'col_name_1':'int','col_name_2':'float64', etc. ...})

따라서 원래 질문을 사용하지만 열 이름을 제공하면 ...

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a, columns=['col_name_1', 'col_name_2', 'col_name_3'])
df = df.astype({'col_name_2':'float64', 'col_name_3':'float64'})

15

다음은 인수로 DataFrame 및 열 목록을 사용하고 열의 모든 데이터를 숫자로 강제 변환하는 함수입니다.

# df is the DataFrame, and column_list is a list of columns as strings (e.g ["col1","col2","col3"])
# dependencies: pandas

def coerce_df_columns_to_numeric(df, column_list):
    df[column_list] = df[column_list].apply(pd.to_numeric, errors='coerce')

예를 들어,

import pandas as pd

def coerce_df_columns_to_numeric(df, column_list):
    df[column_list] = df[column_list].apply(pd.to_numeric, errors='coerce')

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a, columns=['col1','col2','col3'])

coerce_df_columns_to_numeric(df, ['col2','col3'])

열 이름 대신 열 인덱스를 사용하려면 어떻게해야합니까?
jvalenti

8

열에 대해 서로 다른 데이터 유형을 가진 두 개의 데이터 프레임을 만든 다음 함께 추가하는 것은 어떻습니까?

d1 = pd.DataFrame(columns=[ 'float_column' ], dtype=float)
d1 = d1.append(pd.DataFrame(columns=[ 'string_column' ], dtype=str))

결과

In[8}:  d1.dtypes
Out[8]: 
float_column     float64
string_column     object
dtype: object

데이터 프레임을 만든 후에는 첫 번째 열의 부동 소수점 변수와 두 번째 열의 문자열 (또는 원하는 데이터 유형)을 채울 수 있습니다.


4

팬더> = 1.0

다음은 팬더에서 가장 중요한 전환을 요약 한 차트입니다.

여기에 이미지 설명을 입력하십시오

문자열로의 변환은 사소한 것이며 .astype(str)그림에는 표시되지 않습니다.

"하드"대 "소프트"변환

이 문맥에서 "변환"은 텍스트 데이터를 실제 데이터 형식으로 변환 (하드 변환)하거나 개체 열의 데이터에 더 적합한 데이터 형식을 유추하는 것 (소프트 변환)을 의미 할 수 있습니다. 차이점을 설명하기 위해

df = pd.DataFrame({'a': ['1', '2', '3'], 'b': [4, 5, 6]}, dtype=object)
df.dtypes                                                                  

a    object
b    object
dtype: object

# Actually converts string to numeric - hard conversion
df.apply(pd.to_numeric).dtypes                                             

a    int64
b    int64
dtype: object

# Infers better data types for object data - soft conversion
df.infer_objects().dtypes                                                  

a    object  # no change
b     int64
dtype: object

# Same as infer_objects, but converts to equivalent ExtensionType
df.convert_dtypes().dtypes                                                     

1

나는 같은 문제가 있다고 생각했지만 실제로는 문제를 쉽게 해결할 수있는 약간의 차이가 있습니다. 이 질문을 보는 다른 사람들에게는 입력 목록의 형식을 확인하는 것이 좋습니다. 필자의 경우 숫자는 질문에서와 같이 처음에는 문자열이 아닙니다.

a = [['a', 1.2, 4.2], ['b', 70, 0.03], ['x', 5, 0]]

그러나 데이터 프레임을 만들기 전에 목록을 너무 많이 처리하면 유형이 손실되고 모든 것이 문자열이됩니다.

numpy 배열을 통해 데이터 프레임 만들기

df = pd.DataFrame(np.array(a))

df
Out[5]: 
   0    1     2
0  a  1.2   4.2
1  b   70  0.03
2  x    5     0

df[1].dtype
Out[7]: dtype('O')

질문과 동일한 데이터 프레임을 제공하며 열 1과 2의 항목은 문자열로 간주됩니다. 그러나

df = pd.DataFrame(a)

df
Out[10]: 
   0     1     2
0  a   1.2  4.20
1  b  70.0  0.03
2  x   5.0  0.00

df[1].dtype
Out[11]: dtype('float64')

실제로 올바른 형식의 열이있는 데이터 프레임을 제공합니다.


0

팬더 1.0.0부터 시작했습니다 pandas.DataFrame.convert_dtypes. 변환 할 유형을 제어 할 수도 있습니다!

In [40]: df = pd.DataFrame(
    ...:     {
    ...:         "a": pd.Series([1, 2, 3], dtype=np.dtype("int32")),
    ...:         "b": pd.Series(["x", "y", "z"], dtype=np.dtype("O")),
    ...:         "c": pd.Series([True, False, np.nan], dtype=np.dtype("O")),
    ...:         "d": pd.Series(["h", "i", np.nan], dtype=np.dtype("O")),
    ...:         "e": pd.Series([10, np.nan, 20], dtype=np.dtype("float")),
    ...:         "f": pd.Series([np.nan, 100.5, 200], dtype=np.dtype("float")),
    ...:     }
    ...: )

In [41]: dff = df.copy()

In [42]: df 
Out[42]: 
   a  b      c    d     e      f
0  1  x   True    h  10.0    NaN
1  2  y  False    i   NaN  100.5
2  3  z    NaN  NaN  20.0  200.0

In [43]: df.dtypes
Out[43]: 
a      int32
b     object
c     object
d     object
e    float64
f    float64
dtype: object

In [44]: df = df.convert_dtypes()

In [45]: df.dtypes
Out[45]: 
a      Int32
b     string
c    boolean
d     string
e      Int64
f    float64
dtype: object

In [46]: dff = dff.convert_dtypes(convert_boolean = False)

In [47]: dff.dtypes
Out[47]: 
a      Int32
b     string
c     object
d     string
e      Int64
f    float64
dtype: object
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.