Mengubah tipe data kolom di Panda

Saya ingin mengubah tabel, direpresentasikan sebagai daftar list, menjadi Panda DataFrame. Sebagai aplikasi yang sangat sederhana misalnya:

a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a)

Apa cara terbaik untuk mengkonversi kolom untuk jenis yang sesuai, dalam hal ini kolom 2 dan 3 ke mengapung? Apakah ada cara untuk menentukan jenis ketika mengkonversi ke DataFrame? Atau lebih baik untuk membuat DataFrame pertama dan kemudian loop melalui kolom untuk mengubah jenis untuk setiap kolom? Idealnya saya ingin melakukan hal ini dalam cara yang dinamis karena bisa ada ratusan kolom dan saya don't ingin menentukan persis di mana kolom yang jenis. Semua saya dapat menjamin bahwa masing-masing kolom berisi nilai dari tipe yang sama.

Larutan

Anda memiliki tiga pilihan utama untuk mengubah jenis panda:

  1. to_numeric() - menyediakan fungsi untuk aman mengkonversi non-numerik jenis (misalnya string) yang cocok untuk tipe numerik. (Lihat juga to_datetime() dan to_timedelta().)
  2. astype() - mengkonversi (hampir) semua tipe untuk (hampir) semua jenis lain (bahkan jika itu's tidak selalu masuk akal untuk melakukannya). Juga memungkinkan anda untuk mengkonversi ke categorial jenis (sangat berguna).
  3. infer_objects() - sebuah utilitas metode untuk mengkonversi objek kolom memegang Python benda-benda ke panda jenis jika mungkin. Baca terus untuk penjelasan lebih rinci dan penggunaan masing-masing metode ini.

    1. to_numeric()

    Cara terbaik untuk mengkonversi satu atau lebih kolom yang DataFrame untuk nilai-nilai numerik adalah dengan menggunakan pandas.to_numeric(). Fungsi ini akan mencoba untuk mengubah non-numerik, objek (seperti string) ke bilangan bulat atau floating point bilangan yang sesuai.

    Dasar penggunaan

    Masukan untuk to_numeric() adalah Seri atau satu kolom 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

Seperti yang anda lihat, sebuah Seri baru dikembalikan. Ingat untuk menetapkan output ini untuk sebuah variabel atau nama kolom untuk terus menggunakannya:

# convert Series
my_series = pd.to_numeric(my_series)

# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])

Anda juga dapat menggunakannya untuk mengkonversi beberapa kolom dari sebuah DataFrame melalui berlaku() metode:

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

Selama nilai-nilai anda semua bisa diubah, yang's mungkin semua yang anda butuhkan.

Penanganan kesalahan

Tapi bagaimana jika beberapa nilai dapat't akan dikonversi ke tipe numerik? to_numeric() juga mengambil sebuah kesalahan kata kunci argumen yang memungkinkan anda untuk memaksa nilai non-numerik untuk menjadi NaN, atau mengabaikan kolom yang berisi nilai-nilai ini. Berikut ini's contoh menggunakan Serangkaian string s yang memiliki objek dtype:

>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0         1
1         2
2       4.7
3    pandas
4        10
dtype: object

Perilaku default adalah untuk meningkatkan jika itu dapat't mengkonversi nilai. Dalam kasus ini, hal ini dapat't mengatasi string 'panda':

>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string

Daripada gagal, kita mungkin ingin 'panda' dianggap hilang/buruk nilai numerik. Kita dapat memaksa nilai yang tidak valid untuk NaN sebagai berikut menggunakan kesalahan kata kunci argumen:

>>> pd.to_numeric(s, errors='coerce')
0     1.0
1     2.0
2     4.7
3     NaN
4    10.0
dtype: float64

Pilihan ketiga untuk kesalahan hanya untuk mengabaikan operasi jika nilai yang tidak valid ditemui:

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

Ini adalah pilihan terakhir yang sangat berguna ketika anda ingin mengkonversi seluruh DataFrame, tapi don't tidak tahu yang mana dari kolom kita dapat dikonversi andal untuk tipe numerik. Dalam kasus itu hanya menulis:

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

Fungsi yang akan diterapkan untuk masing-masing kolom dari DataFrame. Kolom yang dapat dikonversi ke tipe numerik akan dikonversi, sedangkan kolom yang tidak (misalnya mengandung non-digit string atau jasa) akan ditinggalkan sendirian.

Downcasting

Secara default, konversi dengan to_numeric() akan memberikan anda baik int64 atau float64 dtype (atau apapun bilangan bulat lebar native untuk platform). Yang's biasanya apa yang anda inginkan, tapi bagaimana jika anda ingin menyimpan beberapa memori dan menggunakan lebih kompak dtype, seperti float32, atau int8? to_numeric() memberi anda pilihan untuk tertunduk baik 'integer', 'ditandatangani', 'unsigned', 'float'. Berikut ini's contoh sederhana seri s tipe integer:

>>> s = pd.Series([1, 2, -7])
>>> s
0    1
1    2
2   -7
dtype: int64

Downcasting untuk 'integer' menggunakan bilangan bulat terkecil yang mungkin yang dapat memegang nilai-nilai:

>>> pd.to_numeric(s, downcast='integer')
0    1
1    2
2   -7
dtype: int8

Downcasting untuk 'float' demikian pula picks yang lebih kecil dari normal floating type:

>>> pd.to_numeric(s, downcast='float')
0    1.0
1    2.0
2   -7.0
dtype: float32

2. astype()

The astype() metode memungkinkan anda untuk menjadi eksplisit tentang dtype anda ingin DataFrame atau Seri untuk memiliki. It's sangat serbaguna bahwa anda dapat mencoba dan pergi dari satu jenis yang lain.

Dasar penggunaan

Hanya memilih jenis: anda dapat menggunakan NumPy dtype (misalnya np.int16), beberapa jenis Python (misalnya bool), atau panda-jenis tertentu (seperti kategoris dtype). Memanggil metode pada objek yang anda ingin mengkonversi dan astype() akan mencoba dan mengubahnya untuk anda:

# 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')

Perhatikan aku berkata "coba" - jika astype() tidak tahu bagaimana untuk mengkonversi nilai dalam Seri atau DataFrame, itu akan meningkatkan kesalahan. Misalnya jika anda memiliki sebuah NaN atau inf nilai anda'll mendapatkan error mencoba untuk mengubahnya menjadi integer. Sebagai panda 0.20.0, kesalahan ini dapat ditekan dengan melewati kesalahan='mengabaikan'. Asli objek akan kembali tersentuh.

Berhati-hati

astype() adalah kuat, tetapi kadang-kadang akan mengkonversi nilai-nilai "salah". Misalnya:

>>> s = pd.Series([1, 2, -7])
>>> s
0    1
1    2
2   -7
dtype: int64

Ini adalah kecil bilangan bulat, jadi bagaimana tentang konversi untuk aplikasi yang unsigned 8-bit jenis untuk menyimpan memori?

>>> s.astype(np.uint8)
0      1
1      2
2    249
dtype: uint8

Konversi bekerja, tapi -7 dibungkus bulat untuk menjadi 249 (yaitu 28 - 7)! Mencoba untuk tertunduk menggunakan pd.to_numeric(s, tertunduk='unsigned') malah bisa membantu mencegah kesalahan ini.

3. infer_objects()

Versi 0.21.0 panda memperkenalkan metode infer_objects() untuk mengkonversi kolom DataFrame yang memiliki objek datatype untuk yang lebih spesifik jenis (soft konversi). Sebagai contoh, di sini's DataFrame dengan dua kolom jenis objek. Satu memegang sebenarnya bilangan bulat dan yang lain memegang string yang mewakili bilangan bulat:

>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a    object
b    object
dtype: object

Menggunakan infer_objects(), anda dapat mengubah tipe kolom 'a' untuk int64:

>>> df = df.infer_objects()
>>> df.dtypes
a     int64
b    object
dtype: object

Kolom 'b' telah ditinggalkan sendirian karena nilai string, bukan bilangan bulat. Jika anda ingin mencoba dan memaksa konversi dari kedua kolom ke tipe integer, anda bisa menggunakan df.astype(int) sebagai gantinya.

Komentar (8)

Bagaimana tentang hal ini?

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
Komentar (10)

ini di bawah kode akan mengubah tipe data dari kolom.

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

di tempat jenis data yang dapat anda berikan anda datatype .apa yang anda inginkan seperti str,float,int dll.

Komentar (2)

Berikut adalah fungsi yang mengambil sebagai argumen yang DataFrame dan daftar kolom dan membujuk semua data dalam kolom untuk jumlah.

# 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')

Jadi, untuk contoh:

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'])
Komentar (1)

Ketika saya've hanya diperlukan untuk menentukan kolom tertentu, dan saya ingin menjadi eksplisit, I've digunakan (per DOCS LOKASI):

dataframe = dataframe.astype({'col_name_1':'int','col_name_2':'float64', etc. ...})

Jadi, dengan menggunakan pertanyaan yang asli, tetapi memberikan nama kolom untuk itu ...

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'})
Komentar (0)

Bagaimana menciptakan dua dataframes, masing-masing dengan berbagai tipe data untuk kolom mereka, dan kemudian menambahkan mereka bersama-sama?

d1 = pd.DataFrame(columns=[ 'float_column' ], dtype=float)
d1 = d1.append(pd.DataFrame(columns=[ 'string_column' ], dtype=str))

Hasil

In[8}:  d1.dtypes
Out[8]: 
float_column     float64
string_column     object
dtype: object

Setelah dataframe dibuat, anda dapat mengisinya dengan floating point variabel dalam kolom 1, dan string (atau tipe data apapun yang anda inginkan) di kolom ke-2.

Komentar (0)

Saya pikir saya punya masalah yang sama tapi sebenarnya saya memiliki sedikit perbedaan yang membuat masalah lebih mudah untuk memecahkan. Untuk orang lain melihat pertanyaan ini itu's worth memeriksa format masukan anda daftar. Dalam kasus saya, angka-angka yang awalnya mengapung tidak string seperti pada pertanyaan:

a = [['a', 1.2, 4.2], ['b', 70, 0.03], ['x', 5, 0]]

tapi dengan pengolahan daftar terlalu banyak sebelum membuat dataframe aku kehilangan jenis dan semuanya menjadi sebuah string.

Membuat data frame melalui numpy array

`` df = pd.DataFrame(np.array(a))

df Keluar[5]: 0 1 2 0 1.2 4.2 1 b 70 0.03 2 x 5 0

df[1].dtype Keluar[7]: dtype('O') ``

memberikan data yang sama frame seperti dalam pertanyaan, di mana entri dalam kolom 1 dan 2 dianggap sebagai string. Namun melakukan `` df = pd.DataFrame(a)

df Keluar[10]: 0 1 2 0 1.2 4.20 1 b 70.0 0.03 2 x 5.0 0.00

df[1].dtype Keluar[11]: dtype('float64') `` tidak benar-benar memberikan data frame dengan kolom-kolom pada format yang benar

Komentar (0)