กำหนด dtypes คอลัมน์ดาต้าเฟรมของแพนด้า


113

ฉันต้องการตั้งค่าdtypes ของหลายคอลัมน์ใน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
FYI: df = pd.DataFrame([['a','1'],['b','2']], dtype='int', columns=['x','y'])"ทำงาน" ... แต่: s
Andy Hayden

1
ใช่ "ได้ผล" แน่นอน; คาดเดาไม่ได้ ...
hatmatrix

ปัญหา 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_objectsเลิกใช้แล้วสำหรับแพนด้า 0.12 - 0.16: คุณสามารถใช้เพื่อสรุปประเภทที่ดีกว่า:

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.convertใน R นิดหน่อย; ดี แต่ไม่ปล่อยให้ใครต้องการข้อกำหนดที่ชัดเจนในบางกรณี
hatmatrix

1
ระวังถ้าคุณมีคอลัมน์ที่ต้องเป็นสตริง แต่มีค่าอย่างน้อยหนึ่งค่าที่สามารถแปลงเป็น int ได้ สิ่งที่ต้องมีคือค่าเดียวและทั้งฟิลด์จะถูกแปลงเป็น float64
Michael David Watson

18
ฉันสังเกตเห็นว่าconvert_objects()เลิกใช้งานแล้ว ... ฉันไม่แน่ใจว่ามีอะไรมาแทนที่?
joefromct

6
ในการอนุมานประเภทข้อมูลสำหรับคอลัมน์ออบเจ็กต์อีกครั้งให้ใช้ DataFrame.infer_objects ()
James Tobin

1
@smci โอเคฉันแก้ไขแล้ว มีคำตอบมากมายที่เลิกใช้แล้วฉันต้องหาวิธีหาคำตอบทั้งหมด
Andy Hayden

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

43

คุณสามารถกำหนดประเภทอย่างชัดเจนด้วยแพนด้า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

อีกวิธีหนึ่งในการตั้งค่าประเภทคอลัมน์คือการสร้างอาร์เรย์ระเบียน 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

ประสบปัญหาที่คล้ายกันกับคุณ ในกรณีของฉันฉันมีไฟล์ 1,000 ไฟล์จากบันทึกของซิสโก้ที่ฉันต้องแยกวิเคราะห์ด้วยตนเอง

เพื่อให้มีความยืดหยุ่นกับฟิลด์และประเภทฉันได้ทดสอบสำเร็จโดยใช้ StringIO + read_cvs ซึ่งยอมรับคำสั่งสำหรับข้อกำหนด dtype

ฉันมักจะรับแต่ละไฟล์ (5k-20k บรรทัด) ลงในบัฟเฟอร์และสร้าง dtype dictionaries แบบไดนามิก

ในที่สุดฉันก็เชื่อมต่อ (ด้วยหมวดหมู่ ... ขอบคุณ 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

ไม่มาก .... แต่ทำงาน

หวังว่าจะช่วยได้

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.