パンダの列のデータ型を変更する


805

リストのリストとして表されたテーブルをに変換したい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:df.apply(pd.to_numeric, downcast="integer", errors="ignore")整数列を、値を保持する最小(整数)のdtypeにダウンキャストするようなことができます。
アレックスライリー

回答:


1190

パンダでタイプを変換するには、主に3つのオプションがあります。

  1. to_numeric()-非数値型(文字列など)を適切な数値型に安全に変換する機能を提供します。(も参照してくださいto_datetime()to_timedelta()。)

  2. astype()-(ほぼ)任意のタイプを(ほぼ)他のタイプに変換します(必ずしもそうする必要がない場合でも)。また、カテゴリタイプに変換することもできます(非常に便利です)。

  3. infer_objects() -可能であれば、Pythonオブジェクトを保持するオブジェクト列をパンダ型に変換するユーティリティメソッド。

これらの各方法の詳細な説明と使用方法については、以下をお読みください。


1。 to_numeric()

DataFrameの1つ以上の列を数値に変換する最良の方法は、を使用すること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

デフォルトの動作では、値を変換できない場合に発生します。この場合、文字列「パンダ」に対応できません。

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

の3番目のオプションerrorsは、無効な値が検出された場合に操作を無視することです。

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

この最後のオプションは、DataFrame全体を変換したいが、確実に数値型に変換できる列がわからない場合に特に便利です。その場合は次のように書いてください:

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

関数は、DataFrameの各列に適用されます。数値型に変換できる列は変換されますが、変換できない列(数字以外の文字列や日付を含む列など)はそのままになります。

ダウンキャスト

デフォルトでは、with with to_numeric()はa int64またはfloat64dtype(またはプラットフォーム固有の整数幅)を提供します。

通常はこれで十分ですが、メモリを節約してfloat32、やなどのよりコンパクトなdtypeを使用したい場合はどうすればよいint8でしょうか。

to_numeric()'integer'、 'signed'、 'unsigned'、 'float'のいずれかにダウンキャストするオプションを提供します。一連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を明示的に指定できます。1つのタイプから別のタイプに試してみることができるという点で、非常に用途が広いです。

基本的な使い方

タイプを選択するだけです。NumPydtype(例:)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値がある場合、それを整数に変換しようとするとエラーが発生します。

Pandas 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')代わりにを使用してダウンキャストしようとすると、このエラーを防ぐのに役立ちます。


3。 infer_objects()

パンダのバージョン0.21.0ではinfer_objects()、オブジェクトデータ型を持つDataFrameの列をより具体的な型に変換するメソッド(ソフト変換)が導入されました。

たとえば、オブジェクト型の2つの列を持つDataFrameは次のとおりです。1つは実際の整数を保持し、もう1つは整数を表す文字列を保持します。

>>> 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以来depracatedされる0.17使用- df.to_numeric代わり
マッティライラ

4
ありがとう-この回答を更新する必要があります。注目に値するかもしれませんがpd.to_numeric、そのコンパニオンメソッドは、とは異なり、一度に1つの列でのみ機能しますconvert_objects。APIの置換関数についての議論は進行中のようです。DataFrame全体で機能するメソッドが非常に便利であるため、それが残ることを願っています。
Alex Riley

あなたは、言って、現在のすべての列を変換する最良の方法は何int64にはint32
RoyalTS、2016

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)In [2]:df.dtypes Out [2]:1つのオブジェクト2つのfloat64 3つのfloat64 dtype:オブジェクト
hernamesbarbara 2013

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
Vitaly Isaev

7
@GillBatesはい、辞書にあります。df = pd.DataFrame(a, columns=['one', 'two', 'three'], dtype={'one': str, 'two': int, 'three': float})。しかし、受け入れられる「dtype」値の仕様を見つけるのに苦労しています。リストはいいです(現在私はそうしていますdict(enumerate(my_list)))。
FichteFoll 2016

39

以下のコードは、列のデータ型を変更します。

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

データ型の代わりにデータ型を指定できます。str、float、intなどのように何をしたいですか。


data_typeを使用して文字列 `` `'True'` ``および `` `'False'` ``を含む列にこれを適用するとbool、すべてがに変更されることに注意してくださいTrue
H.ヴァブリ

このオプションは、「カテゴリ」タイプに変換することもできます
neves

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

それぞれが列のデータ型が異なる2つのデータフレームを作成し、それらを一緒に追加してみませんか?

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

データフレームが作成された後、1列目には浮動小数点変数を、2列目には文字列(または任意のデータ型)を入力できます。


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.