パンダのデータフレーム列のdtypeを割り当てる


110

dtype複数の列のs を設定したいpd.Dataframe(ファイルが対応していなかったため、リストのリストに手動で解析しなければならないファイルがありますpd.read_csv

import pandas as pd
print pd.DataFrame([['a','1'],['b','2']],
                   dtype={'x':'object','y':'int'},
                   columns=['x','y'])

私は得る

ValueError: entry not a 2- or 3- tuple

それらを設定できる唯一の方法は、各列変数をループしてで再キャストすることastypeです。

dtypes = {'x':'object','y':'int'}
mydata = pd.DataFrame([['a','1'],['b','2']],
                      columns=['x','y'])
for c in mydata.columns:
    mydata[c] = mydata[c].astype(dtypes[c])
print mydata['y'].dtype   #=> int64

もっと良い方法はありますか?


これはおそらく良いバグ/機能のリクエストでしょう。現在、dtype argが何をしているのかわかりません(スカラーを渡すことはできますが、厳密ではありません)...
Andy Hayden

2
参考までに:df = pd.DataFrame([['a','1'],['b','2']], dtype='int', columns=['x','y'])「機能する」...しかし:s
Andy Hayden 14年

1
ええ、確かに「機能します」。予期せぬ...
ハットマトリックス2014年

このGitHubの問題は間もなく関連するようになる可能性があります:github.com/pydata/pandas/issues/9287
Amelio Vazquez-Reina

回答:


65

0.17以降、明示的な変換を使用する必要があります。

pd.to_datetime, pd.to_timedelta and pd.to_numeric

(下記のとおり、「マジック」convert_objectsはなくなり、0.17で非推奨になりました)

df = pd.DataFrame({'x': {0: 'a', 1: 'b'}, 'y': {0: '1', 1: '2'}, 'z': {0: '2018-05-01', 1: '2018-05-02'}})

df.dtypes

x    object
y    object
z    object
dtype: object

df

   x  y           z
0  a  1  2018-05-01
1  b  2  2018-05-02

これらを変換する各列に適用できます。

df["y"] = pd.to_numeric(df["y"])
df["z"] = pd.to_datetime(df["z"])    
df

   x  y          z
0  a  1 2018-05-01
1  b  2 2018-05-02

df.dtypes

x            object
y             int64
z    datetime64[ns]
dtype: object

dtypeが更新されていることを確認します。


パンダconvert_objects0.12-0.16の古い/廃止された回答:より良いdtypeを推測するために使用できます:

In [21]: df
Out[21]: 
   x  y
0  a  1
1  b  2

In [22]: df.dtypes
Out[22]: 
x    object
y    object
dtype: object

In [23]: df.convert_objects(convert_numeric=True)
Out[23]: 
   x  y
0  a  1
1  b  2

In [24]: df.convert_objects(convert_numeric=True).dtypes
Out[24]: 
x    object
y     int64
dtype: object

マジック!(非推奨になるのは悲しいことです。)


2
type.convertRのように いいですが、場合によっては明示的な仕様を希望する人もいます。
Hatmatrix 2014年

1
文字列である必要があるが、intに変換できる値が少なくとも1つ含まれている列がある場合は注意してください。必要なのは1つの値だけであり、フィールド全体がfloat64に変換されます
Michael David Watson、

18
convert_objects()非推奨になっていることに気付きました...何が置き換えられたのかわかりませんか?
joefromct

6
オブジェクト列のデータdtypeを再推論するには、DataFrame.infer_objects()を使用します
James Tobin

1
@smci大丈夫、私は編集しました。非推奨の回答がたくさんあります。それらすべてを見つける方法を考え出す必要があります。
アンディヘイデン

62

私などのGoogle(など)から来ている人:

convert_objects 0.17以降廃止されました-使用すると、次のような警告が表示されます。

FutureWarning: convert_objects is deprecated.  Use the data-type specific converters 
pd.to_datetime, pd.to_timedelta and pd.to_numeric.

次のようなことをする必要があります。


あなたがpd.to_datetime, to_timedelta, to_numericこれのいくつかの例を投げた場合、受け入れられた答えになるはずです。
smci 2018年

41

あなたはパンダDataFrame.astype(dtype, copy=True, raise_on_error=True, **kwargs)で明示的にタイプを設定し、あなたがしたいdtypesで辞書を渡すことができますdtype

ここに例があります:

import pandas as pd
wheel_number = 5
car_name = 'jeep'
minutes_spent = 4.5

# set the columns
data_columns = ['wheel_number', 'car_name', 'minutes_spent']

# create an empty dataframe
data_df = pd.DataFrame(columns = data_columns)
df_temp = pd.DataFrame([[wheel_number, car_name, minutes_spent]],columns = data_columns)
data_df = data_df.append(df_temp, ignore_index=True) 

In [11]: data_df.dtypes
Out[11]:
wheel_number     float64
car_name          object
minutes_spent    float64
dtype: object

data_df = data_df.astype(dtype= {"wheel_number":"int64",
        "car_name":"object","minutes_spent":"float64"})

変更されたことがわかります

In [18]: data_df.dtypes
Out[18]:
wheel_number       int64
car_name          object
minutes_spent    float64

13

列のタイプを設定するもう1つの方法は、最初に目的のタイプでnumpyレコード配列を作成し、それを入力してから、DataFrameコンストラクターに渡すことです。

import pandas as pd
import numpy as np    

x = np.empty((10,), dtype=[('x', np.uint8), ('y', np.float64)])
df = pd.DataFrame(x)

df.dtypes ->

x      uint8
y    float64

0

あなたと同じような問題に直面しています。私の場合、手動で解析する必要があるCiscoログからの1000個のファイルがあります。

フィールドとタイプに柔軟に対応するために、実際にはdtype仕様のdictを受け入れるStringIO + read_cvsを使用してテストに成功しました。

私は通常、各ファイル(5kから20k行)をバッファーに入れ、dtype辞書を動的に作成します。

最終的に私はこれらのデータフレームを(カテゴリカル... 0.19のおかげで)大きなデータフレームに連結し、hdf5にダンプします。

これらの線に沿った何か

import pandas as pd
import io 

output = io.StringIO()
output.write('A,1,20,31\n')
output.write('B,2,21,32\n')
output.write('C,3,22,33\n')
output.write('D,4,23,34\n')

output.seek(0)


df=pd.read_csv(output, header=None,
        names=["A","B","C","D"],
        dtype={"A":"category","B":"float32","C":"int32","D":"float64"},
        sep=","
       )

df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 4 columns):
A    5 non-null category
B    5 non-null float32
C    5 non-null int32
D    5 non-null float64
dtypes: category(1), float32(1), float64(1), int32(1)
memory usage: 205.0 bytes
None

それほどpythonicではない......しかし仕事をします

それが役に立てば幸い。

JC


0

型指定されたnp.arraysを使用してから、データと列の名前を辞書として渡すほうがよいでしょう。

import numpy as np
import pandas as pd
# Feature: np arrays are 1: efficient, 2: can be pre-sized
x = np.array(['a', 'b'], dtype=object)
y = np.array([ 1 ,  2 ], dtype=np.int32)
df = pd.DataFrame({
   'x' : x,    # Feature: column name is near data array
   'y' : y,
   }
 )
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.