Bạn có ba tùy chọn chính để chuyển đổi các loại trong gấu trúc:
to_numeric()
- cung cấp chức năng để chuyển đổi một cách an toàn các loại không phải số (ví dụ: chuỗi) sang loại số phù hợp. (Xem thêm to_datetime()
và to_timedelta()
.)
astype()
- chuyển đổi (gần như) bất kỳ loại nào sang (gần như) bất kỳ loại nào khác (ngay cả khi không nhất thiết phải làm như vậy). Cũng cho phép bạn chuyển đổi sang các loại chiến lược (rất hữu ích).
infer_objects()
- một phương thức tiện ích để chuyển đổi các cột đối tượng giữ các đối tượng Python thành một loại gấu trúc nếu có thể.
Đọc để giải thích chi tiết hơn và sử dụng từng phương pháp này.
1. to_numeric()
Cách tốt nhất để chuyển đổi một hoặc nhiều cột của DataFrame thành các giá trị số là sử dụng pandas.to_numeric()
.
Hàm này sẽ cố gắng thay đổi các đối tượng không phải là số (chẳng hạn như chuỗi) thành số nguyên hoặc số dấu phẩy động nếu thích hợp.
Sử dụng cơ bản
Đầu vào to_numeric()
là một Sê-ri hoặc một cột của Khung dữ liệu.
>>> 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
Như bạn có thể thấy, một Series mới được trả về. Hãy nhớ gán đầu ra này cho một biến hoặc tên cột để tiếp tục sử dụng nó:
# convert Series
my_series = pd.to_numeric(my_series)
# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])
Bạn cũng có thể sử dụng nó để chuyển đổi nhiều cột của DataFrame thông qua apply()
phương thức:
# 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)
Miễn là tất cả các giá trị của bạn có thể được chuyển đổi, đó có thể là tất cả những gì bạn cần.
Xử lý lỗi
Nhưng nếu một số giá trị không thể được chuyển đổi thành một loại số thì sao?
to_numeric()
cũng có một errors
đối số từ khóa cho phép bạn buộc các giá trị không phải là số NaN
hoặc đơn giản là bỏ qua các cột có chứa các giá trị này.
Dưới đây là một ví dụ sử dụng Chuỗi chuỗi s
có dtype đối tượng:
>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0 1
1 2
2 4.7
3 pandas
4 10
dtype: object
Hành vi mặc định là nâng cao nếu nó không thể chuyển đổi một giá trị. Trong trường hợp này, nó không thể đối phó với chuỗi 'gấu trúc':
>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string
Thay vì thất bại, chúng tôi có thể muốn 'gấu trúc' được coi là một giá trị số bị thiếu / xấu. Chúng tôi có thể ép buộc các giá trị không hợp lệ NaN
như sau bằng cách sử dụng errors
đối số từ khóa:
>>> pd.to_numeric(s, errors='coerce')
0 1.0
1 2.0
2 4.7
3 NaN
4 10.0
dtype: float64
Tùy chọn thứ ba errors
chỉ là bỏ qua thao tác nếu gặp phải giá trị không hợp lệ:
>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched
Tùy chọn cuối cùng này đặc biệt hữu ích khi bạn muốn chuyển đổi toàn bộ DataFrame của mình, nhưng không biết cột nào của chúng tôi có thể được chuyển đổi đáng tin cậy thành một loại số. Trong trường hợp đó chỉ cần viết:
df.apply(pd.to_numeric, errors='ignore')
Hàm này sẽ được áp dụng cho từng cột của DataFrame. Các cột có thể được chuyển đổi thành một loại số sẽ được chuyển đổi, trong khi các cột không thể (ví dụ: chúng chứa các chuỗi hoặc ngày không có chữ số) sẽ được để lại một mình.
Buồn bã
Theo mặc định, chuyển đổi với to_numeric()
sẽ cung cấp cho bạn một int64
hoặc float64
dtype (hoặc bất kỳ chiều rộng số nguyên nào có nguồn gốc từ nền tảng của bạn).
Đó thường là những gì bạn muốn, nhưng nếu bạn muốn tiết kiệm bộ nhớ và sử dụng một loại dtype nhỏ gọn hơn, như float32
, hoặc int8
?
to_numeric()
cung cấp cho bạn tùy chọn để downcast thành 'số nguyên', 'đã ký', 'không dấu', 'float'. Đây là một ví dụ cho một loạt s
các kiểu số nguyên đơn giản :
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Downcasting đến 'số nguyên' sử dụng số nguyên nhỏ nhất có thể có thể chứa các giá trị:
>>> pd.to_numeric(s, downcast='integer')
0 1
1 2
2 -7
dtype: int8
Downcasting để 'float' tương tự chọn một kiểu nổi nhỏ hơn bình thường:
>>> pd.to_numeric(s, downcast='float')
0 1.0
1 2.0
2 -7.0
dtype: float32
2. astype()
Các astype()
phương pháp cho phép bạn được rõ ràng về các dtype bạn muốn DataFrame hay Series của bạn để có. Nó rất linh hoạt ở chỗ bạn có thể thử và đi từ loại này sang loại khác.
Sử dụng cơ bản
Chỉ cần chọn một loại: bạn có thể sử dụng một loại dtype NumPy (ví dụ np.int16
), một số loại Python (ví dụ bool) hoặc các loại dành riêng cho gấu trúc (như loại dtype phân loại).
Gọi phương thức trên đối tượng bạn muốn chuyển đổi và astype()
sẽ thử và chuyển đổi nó cho bạn:
# 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')
Lưu ý rằng tôi đã nói "thử" - nếu astype()
không biết cách chuyển đổi giá trị trong Sê-ri hoặc Khung dữ liệu, nó sẽ phát sinh lỗi. Ví dụ: nếu bạn có một NaN
hoặc inf
giá trị, bạn sẽ gặp lỗi khi chuyển đổi nó thành số nguyên.
Kể từ gấu trúc 0.20.0, lỗi này có thể được loại bỏ bằng cách vượt qua errors='ignore'
. Đối tượng ban đầu của bạn sẽ được trả lại không bị ảnh hưởng.
Hãy cẩn thận
astype()
là mạnh mẽ, nhưng đôi khi nó sẽ chuyển đổi các giá trị "không chính xác". Ví dụ:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Đây là các số nguyên nhỏ, vậy làm thế nào về việc chuyển đổi sang loại 8 bit không dấu để tiết kiệm bộ nhớ?
>>> s.astype(np.uint8)
0 1
1 2
2 249
dtype: uint8
Việc chuyển đổi đã hoạt động, nhưng -7 đã được bao quanh để trở thành 249 (tức là 2 8 - 7)!
pd.to_numeric(s, downcast='unsigned')
Thay vào đó, cố gắng để downcast sử dụng có thể giúp ngăn ngừa lỗi này.
3. infer_objects()
Phiên bản 0.21.0 của gấu trúc đã giới thiệu phương thức infer_objects()
chuyển đổi các cột của DataFrame có kiểu dữ liệu đối tượng thành một loại cụ thể hơn (chuyển đổi mềm).
Ví dụ: đây là một DataFrame có hai cột loại đối tượng. Một số giữ số nguyên thực tế và số còn lại giữ các chuỗi đại diện cho số nguyên:
>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a object
b object
dtype: object
Sử dụng infer_objects()
, bạn có thể thay đổi loại cột 'a' thành int64:
>>> df = df.infer_objects()
>>> df.dtypes
a int64
b object
dtype: object
Cột 'b' đã bị bỏ lại một mình vì các giá trị của nó là các chuỗi, không phải là số nguyên. Nếu bạn muốn thử và buộc chuyển đổi cả hai cột thành một kiểu số nguyên, bạn có thể sử dụng df.astype(int)
thay thế.