Development Tip

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

yourdevel 2020. 9. 30. 11:38
반응형

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


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

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

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


Pandas에서 유형을 변환하는 세 가지 주요 옵션이 있습니다.

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

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

  3. infer_objects() -가능한 경우 Python 객체를 보유하는 객체 열을 pandas 유형으로 변환하는 유틸리티 메서드.

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


1. to_numeric()

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

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

기본 사용법

의 입력 to_numeric()은 Series 또는 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

실패하기보다는 'pandas'가 누락 된 / 잘못된 숫자 값으로 간주되기를 원할 수 있습니다. 키워드 인수를 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 (또는 플랫폼에 고유 한 정수 너비)이 제공됩니다.

일반적으로 원하는 것이지만 메모리를 절약하고 float32, 또는 int8? 와 같은 더 컴팩트 한 dtype을 사용하려면 어떻게해야합니까?

to_numeric()'integer', 'signed', 'unsigned', 'float'로 다운 캐스트 할 수있는 옵션을 제공합니다. 다음은 간단한 s정수 유형 의 예입니다 .

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

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

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

Downcasting to 'float' similarly picks a smaller than normal floating type:

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

2. astype()

The astype() method enables you to be explicit about the dtype you want your DataFrame or Series to have. It's very versatile in that you can try and go from one type to the any other.

Basic usage

Just pick a type: you can use a NumPy dtype (e.g. np.int16), some Python types (e.g. bool), or pandas-specific types (like the categorical dtype).

Call the method on the object you want to convert and astype() will try and convert it for you:

# 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')

Notice I said "try" - if astype() does not know how to convert a value in the Series or DataFrame, it will raise an error. For example if you have a NaN or inf value you'll get an error trying to convert it to an integer.

As of pandas 0.20.0, this error can be suppressed by passing errors='ignore'. Your original object will be return untouched.

Be careful

astype() is powerful, but it will sometimes convert values "incorrectly". For example:

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

These are small integers, so how about converting to an unsigned 8-bit type to save memory?

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

The conversion worked, but the -7 was wrapped round to become 249 (i.e. 28 - 7)!

Trying to downcast using pd.to_numeric(s, downcast='unsigned') instead could help prevent this error.


3. infer_objects()

Version 0.21.0 of pandas introduced the method infer_objects() for converting columns of a DataFrame that have an object datatype to a more specific type (soft conversions).

For example, here's a DataFrame with two columns of object type. One holds actual integers and the other holds strings representing integers:

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

Using infer_objects(), you can change the type of column 'a' to int64:

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

Column 'b' has been left alone since its values were strings, not integers. If you wanted to try and force the conversion of both columns to an integer type, you could use df.astype(int) instead.


How about this?

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

this below code will change datatype of column.

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

in place of data type you can give your datatype .what do you want like str,float,int etc.


Here is a function that takes as its arguments a DataFrame and a list of columns and coerces all data in the columns to numbers.

# 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')

So, for your example:

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'])

When I've only needed to specify specific columns, and I want to be explicit, I've used (per DOCS LOCATION):

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

So, using the original question, but providing column names to it ...

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'})

How about creating two dataframes, each with different data types for their columns, and then appending them together?

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

Results

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

After the dataframe is created, you can populate it with floating point variables in the 1st column, and strings (or any data type you desire) in the 2nd column.


I thought I had the same problem but actually I have a slight difference that makes the problem easier to solve. For others looking at this question it's worth checking the format of your input list. In my case the numbers are initially floats not strings as in the question:

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

but by processing the list too much before creating the dataframe I lose the types and everything becomes a string.

Creating the data frame via a numpy array

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')

gives the same data frame as in the question, where the entries in columns 1 and 2 are considered as strings. However doing

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')

does actually give a data frame with the columns in the correct format

참고URL : https://stackoverflow.com/questions/15891038/change-data-type-of-columns-in-pandas

반응형