Gán các loại cột khung dữ liệu gấu trúc


110

Tôi muốn đặt dtypenhiều cột trong đó pd.Dataframe(tôi có một tệp mà tôi phải phân tích cú pháp theo cách thủ công thành danh sách các danh sách, vì tệp không thể sửa được pd.read_csv)

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

tôi có

ValueError: entry not a 2- or 3- tuple

Cách duy nhất tôi có thể đặt chúng là bằng cách lặp qua từng biến cột và đọc lại với 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

Có cách nào tốt hơn?


Đây có lẽ sẽ là một tốt lỗi / tính năng yêu cầu , hiện nay tôi không chắc chắn những gì dtype arg đang làm (bạn có thể vượt qua nó một vô hướng, nhưng nó không phải là nghiêm ngặt) ...
Andy Hayden

2
FYI: df = pd.DataFrame([['a','1'],['b','2']], dtype='int', columns=['x','y'])"tác phẩm" ... nhưng: s
Andy Hayden

1
Vâng, "hoạt động" thực sự; không thể đoán trước được ...
hatmatrix

Vấn đề GitHub này có thể sẽ sớm trở nên thích hợp: github.com/pydata/pandas/issues/9287
Amelio Vazquez-Reina

Câu trả lời:


65

Kể từ 0,17, bạn phải sử dụng các chuyển đổi rõ ràng:

pd.to_datetime, pd.to_timedelta and pd.to_numeric

(Như đã đề cập bên dưới, không còn "ma thuật" nào nữa, convert_objectsđã không còn được dùng trong 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

Bạn có thể áp dụng những điều này cho từng cột bạn muốn chuyển đổi:

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

và xác nhận loại đã được cập nhật.


CÂU TRẢ LỜI CŨ / KHÔNG DÙNG cho gấu trúc 0,12 - 0,16: Bạn có thể sử dụng convert_objectsđể suy ra các kiểu tốt hơn:

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

Ma thuật! (Thật buồn khi thấy nó không được dùng nữa.)


2
như type.converttrong R một chút; tốt nhưng không để lại một người mong muốn các thông số kỹ thuật rõ ràng trong một số trường hợp.
hatmatrix

1
Hãy cẩn thận nếu bạn có một cột cần phải là một chuỗi nhưng chứa ít nhất một giá trị có thể được chuyển đổi thành int. Tất cả những gì cần là một giá trị và toàn bộ trường được chuyển đổi thành float64
Michael David Watson

18
Tôi nhận thấy convert_objects()đã không còn được dùng nữa ... tôi không chắc cái gì đã thay thế nó?
joefromct

6
Để tái suy luận dtypes dữ liệu cho cột đối tượng, DataFrame.infer_objects sử dụng ()
James Tobin

1
@smci được rồi, tôi đã chỉnh sửa. Có rất nhiều câu trả lời không được dùng nữa, tôi cần tìm ra cách để tìm tất cả.
Andy Hayden

62

Đối với những người đến từ Google (v.v.), chẳng hạn như tôi:

convert_objects đã không được dùng nữa kể từ 0.17 - nếu bạn sử dụng nó, bạn sẽ nhận được cảnh báo như sau:

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

Bạn nên làm như sau:


Nếu bạn đưa ra một số ví dụ về pd.to_datetime, to_timedelta, to_numericđiều này thì câu trả lời được chấp nhận.
smci

41

bạn có thể đặt các kiểu rõ ràng với gấu trúc DataFrame.astype(dtype, copy=True, raise_on_error=True, **kwargs)và chuyển vào từ điển các kiểu bạn muốndtype

đây là một ví dụ:

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

bây giờ bạn có thể thấy rằng nó đã thay đổi

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

13

Một cách khác để đặt các kiểu cột là trước tiên hãy xây dựng một mảng bản ghi numpy với các kiểu mong muốn của bạn, điền vào nó và sau đó chuyển nó cho một phương thức khởi tạo 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

đối mặt với vấn đề tương tự với bạn. Trong trường hợp của tôi, tôi có 1000 tệp từ nhật ký cisco mà tôi cần phân tích cú pháp theo cách thủ công.

Để linh hoạt với các trường và kiểu, tôi đã thử nghiệm thành công bằng cách sử dụng StringIO + read_cvs mà thực sự chấp nhận một chính tả cho đặc tả loại dtype.

Tôi thường lấy từng tệp (5k-20k dòng) vào bộ đệm và tạo động từ điển dtype.

Cuối cùng tôi nối (với phân loại ... nhờ 0,19) các khung dữ liệu này vào một khung dữ liệu lớn mà tôi kết xuất vào hdf5.

Một cái gì đó dọc theo những dòng này

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

Không phải là rất khó hiểu .... nhưng có công việc

Hy vọng nó giúp.

JC


0

Tốt hơn hết bạn nên sử dụng np.arrays đã nhập, sau đó chuyển dữ liệu và tên cột làm từ điển.

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,
   }
 )
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.