pandas 數據類型轉換

數據處理過程的數據類型

  • 當利用pandas進行數據處理的時候,經常會遇到數據類型的問題,當拿到數據的時候,首先需要確定拿到的是正確類型的數據,一般通過數據類型的轉化,這篇文章就介紹pandas裡面的數據類型(data types也就是常用的dtyps),以及pandas與numpy之間的數據對應關係。

pandas 數據類型轉換


  • 主要介紹object,int64,float64,datetime64,bool等幾種類型,category與timedelta兩種類型會單獨的在其他文章中進行介紹。當然本文中也會涉及簡單的介紹。

數據類型的問題一般都是出了問題之後才會發現的,所以有了一些經驗之後就會拿到數據之後,就直接看數據類型,是否與自己想要處理的數據格式一致,這樣可以從一開始避免一些尷尬的問題出現。那麼我們以一個簡單的例子,利用jupyter notebook進行一個數據類型的介紹。

<code>####按照慣例導入兩個常用的數據處理的包,numpy與pandas
import numpy as np
import pandas as pd
# 從csv文件讀取數據,數據表格中只有5行,裡面包含了float,string,int三種數據python類型,也就是分別對應的pandas的float64,object,int64
# csv文件中共有六列,第一列是表頭,其餘是數據。
df = pd.read_csv("sales_data_types.csv")
print(df)Customer Number Customer Name 2016 2017 \\
0 10002 Quest Industries $125,000.00 $162,500.00
1 552278 Smith Plumbing $920,000.00 $1,012,000.00
2 23477 ACME Industrial $50,000.00 $62,500.00
3 24900 Brekke LTD $350,000.00 $490,000.00
4 651029 Harbor Co $15,000.00 $12,750.00

Percent Growth Jan Units Month Day Year Active
0 30.00% 500 1 10 2015 Y

1 10.00% 700 6 15 2014 Y
2 25.00% 125 3 29 2016 Y
3 4.00% 75 10 27 2015 Y
4 -15.00% Closed 2 2 2014 Ndf.dtypesCustomer Number int64
Customer Name object
2016 object
2017 object
Percent Growth object
Jan Units object
Month int64
Day int64
Year int64
Active object
dtype: object# 假如想得到2016年與2017年的數據總和,可以嘗試,但並不是我們需要的答案,因為這兩列中的數據類型是object,執行該操作之後,得到是一個更加長的字符串,
# 當然我們可以通過df.info() 來獲得關於數據框的更多的詳細信息,
df['2016']+df['2017']0 $125,000.00 $162,500.00
1 $920,000.00 $1,012,000.00
2 $50,000.00 $62,500.00
3 $350,000.00 $490,000.00
4 $15,000.00 $12,750.00
dtype: objectdf.info()
# Customer Number 列是float64,然而應該是int64
# 2016 2017兩列的數據是object,並不是float64或者int64格式
# Percent以及Jan Units 也是objects而不是數字格式
# Month,Day以及Year應該轉化為datetime64[ns]格式
# Active 列應該是布爾值
# 如果不做數據清洗,很難進行下一步的數據分析,為了進行數據格式的轉化,pandas裡面有三種比較常用的方法
# 1. astype()強制轉化數據類型
# 2. 通過創建自定義的函數進行數據轉化
# 3. pandas提供的to_nueric()以及to_datetime()<class>

RangeIndex: 5 entries, 0 to 4
Data columns (total 10 columns):
Customer Number 5 non-null int64
Customer Name 5 non-null object
2016 5 non-null object
2017 5 non-null object
Percent Growth 5 non-null object
Jan Units 5 non-null object
Month 5 non-null int64
Day 5 non-null int64
Year 5 non-null int64
Active 5 non-null object
dtypes: int64(4), object(6)
memory usage: 480.0+ bytes/<class>/<code>

首先介紹最常用的astype()

比如可以通過astype()將第一列的數據轉化為整數int類型

<code>df['Customer Number'].astype("int")
# 這樣的操作並沒有改變原始的數據框,而只是返回的一個拷貝0 10002
1 552278
2 23477
3 24900
4 651029
Name: Customer Number, dtype: int32# 想要真正的改變數據框,通常需要通過賦值來進行,比如
df["Customer Number"] = df["Customer Number"].astype("int")
print(df)
print("--------"*10)
print(df.dtypes)Customer Number Customer Name 2016 2017 \\
0 10002 Quest Industries $125,000.00 $162,500.00
1 552278 Smith Plumbing $920,000.00 $1,012,000.00
2 23477 ACME Industrial $50,000.00 $62,500.00
3 24900 Brekke LTD $350,000.00 $490,000.00
4 651029 Harbor Co $15,000.00 $12,750.00

Percent Growth Jan Units Month Day Year Active
0 30.00% 500 1 10 2015 Y
1 10.00% 700 6 15 2014 Y
2 25.00% 125 3 29 2016 Y

3 4.00% 75 10 27 2015 Y
4 -15.00% Closed 2 2 2014 N
--------------------------------------------------------------------------------
Customer Number int32
Customer Name object
2016 object
2017 object
Percent Growth object
Jan Units object
Month int64
Day int64
Year int64
Active object
dtype: object# 通過賦值在原始的數據框基礎上進行了數據轉化,可以重新看一下我們新生成的數據框
print(df)Customer Number Customer Name 2016 2017 \\
0 10002 Quest Industries $125,000.00 $162,500.00
1 552278 Smith Plumbing $920,000.00 $1,012,000.00
2 23477 ACME Industrial $50,000.00 $62,500.00
3 24900 Brekke LTD $350,000.00 $490,000.00
4 651029 Harbor Co $15,000.00 $12,750.00

Percent Growth Jan Units Month Day Year Active
0 30.00% 500 1 10 2015 Y
1 10.00% 700 6 15 2014 Y
2 25.00% 125 3 29 2016 Y
3 4.00% 75 10 27 2015 Y
4 -15.00% Closed 2 2 2014 N# 然後像2016,2017 Percent Growth,Jan Units 這幾列帶有特殊符號的object是不能直接通過astype("flaot)方法進行轉化的,
# 這與python中的字符串轉化為浮點數,都要求原始的字符都只能含有數字本身,不能含有其他的特殊字符
# 我們可以試著將將Active列轉化為布爾值,看一下到底會發生什麼,五個結果全是True,說明並沒有起到什麼作用#df["Active"].astype("bool")df['2016'].astype('float')---------------------------------------------------------------------------

ValueError Traceback (most recent call last)

<ipython-input-19-47cc9d68cd65> in <module>()
----> 1 df['2016'].astype('float')


C:\\Anaconda3\\lib\\site-packages\\pandas\\core\\generic.py in astype(self, dtype, copy, raise_on_error, **kwargs)
3052 # else, only a single dtype is given
3053 new_data = self._data.astype(dtype=dtype, copy=copy,
-> 3054 raise_on_error=raise_on_error, **kwargs)
3055 return self._constructor(new_data).__finalize__(self)
3056


C:\\Anaconda3\\lib\\site-packages\\pandas\\core\\internals.py in astype(self, dtype, **kwargs)
3187
3188 def astype(self, dtype, **kwargs):
-> 3189 return self.apply('astype', dtype=dtype, **kwargs)
3190
3191 def convert(self, **kwargs):


C:\\Anaconda3\\lib\\site-packages\\pandas\\core\\internals.py in apply(self, f, axes, filter, do_integrity_check, consolidate, **kwargs)
3054
3055 kwargs['mgr'] = self
-> 3056 applied = getattr(b, f)(**kwargs)
3057 result_blocks = _extend_blocks(applied, result_blocks)
3058


C:\\Anaconda3\\lib\\site-packages\\pandas\\core\\internals.py in astype(self, dtype, copy, raise_on_error, values, **kwargs)
459 **kwargs):
460 return self._astype(dtype, copy=copy, raise_on_error=raise_on_error,
--> 461 values=values, **kwargs)
462
463 def _astype(self, dtype, copy=False, raise_on_error=True, values=None,


C:\\Anaconda3\\lib\\site-packages\\pandas\\core\\internals.py in _astype(self, dtype, copy, raise_on_error, values, klass, mgr, **kwargs)
502
503 # _astype_nansafe works fine with 1-d only
--> 504 values = _astype_nansafe(values.ravel(), dtype, copy=True)
505 values = values.reshape(self.shape)
506


C:\\Anaconda3\\lib\\site-packages\\pandas\\types\\cast.py in _astype_nansafe(arr, dtype, copy)
535
536 if copy:
--> 537 return arr.astype(dtype)
538 return arr.view(dtype)
539


ValueError: could not convert string to float: '$15,000.00 '/<module>/<ipython-input-19-47cc9d68cd65>/<code>

以上的問題說明了一些問題

  • 如果數據是純淨的數據,可以轉化為數字
  • astype基本也就是兩種用作,數字轉化為單純字符串,單純數字的字符串轉化為數字,含有其他的非數字的字符串是不能通過astype進行轉化的。
  • 需要引入其他的方法進行轉化,也就有了下面的自定義函數方法

通過自定義函數清理數據

  • 通過下面的函數可以將貨幣進行轉化
<code>def convert_currency(var):
"""
convert the string number to a float
_ 去除$
- 去除逗號,
- 轉化為浮點數類型
"""
new_value = var.replace(",","").replace("$","")
return float(new_value)# 通過replace函數將$以及逗號去掉,然後字符串轉化為浮點數,讓pandas選擇pandas認為合適的特定類型,float或者int,該例子中將數據轉化為了float64
# 通過pandas中的apply函數將2016列中的數據全部轉化

df["2016"].apply(convert_currency)0 125000.0
1 920000.0
2 50000.0
3 350000.0
4 15000.0
Name: 2016, dtype: float64# 當然可以通過lambda 函數將這個比較簡單的函數一行帶過
df["2016"].apply(lambda x: x.replace(",","").replace("$","")).astype("float64")0 125000.0
1 920000.0
2 50000.0
3 350000.0
4 15000.0
Name: 2016, dtype: float64#同樣可以利用lambda表達式將PercentGrowth進行數據清理
df["Percent Growth"].apply(lambda x: x.replace("%","")).astype("float")/1000 0.30
1 0.10
2 0.25
3 0.04
4 -0.15
Name: Percent Growth, dtype: float64# 同樣可以通過自定義函數進行解決,結果同上
# 最後一個自定義函數是利用np.where() function 將Active 列轉化為布爾值。
df["Active"] = np.where(df["Active"] == "Y", True, False)

df["Active"]0 True
1 True
2 True
3 True
4 False
Name: Active, dtype: bool# 此時可查看一下數據格式
df["2016"]=df["2016"].apply(lambda x: x.replace(",","").replace("$","")).astype("float64")
df["2017"]=df["2017"].apply(lambda x: x.replace(",","").replace("$","")).astype("float64")
df["Percent Growth"]=df["Percent Growth"].apply(lambda x: x.replace("%","")).astype("float")/100
df.dtypesCustomer Number int32
Customer Name object
2016 float64
2017 float64
Percent Growth float64
Jan Units object
Month int64
Day int64
Year int64
Active bool
dtype: object# 再次查看DataFrame

# 此時只有Jan Units中格式需要轉化,以及年月日的合併,可以利用pandas中自帶的幾個函數進行處理
print(df)Customer Number Customer Name 2016 2017 Percent Growth \\
0 10002 Quest Industries 125000.0 162500.0 0.30
1 552278 Smith Plumbing 920000.0 1012000.0 0.10
2 23477 ACME Industrial 50000.0 62500.0 0.25
3 24900 Brekke LTD 350000.0 490000.0 0.04
4 651029 Harbor Co 15000.0 12750.0 -0.15

Jan Units Month Day Year Active
0 500 1 10 2015 True
1 700 6 15 2014 True
2 125 3 29 2016 True
3 75 10 27 2015 True
4 Closed 2 2 2014 False/<code>

利用pandas中函數進行處理

<code># pandas中pd.to_numeric()處理Jan Units中的數據
pd.to_numeric(df["Jan Units"],errors='coerce').fillna(0)0 500.0
1 700.0
2 125.0
3 75.0
4 0.0
Name: Jan Units, dtype: float64# 最後利用pd.to_datatime()將年月日進行合併
pd.to_datetime(df[['Month', 'Day', 'Year']])0 2015-01-10
1 2014-06-15
2 2016-03-29
3 2015-10-27
4 2014-02-02
dtype: datetime64[ns]# 做到這裡不要忘記重新賦值,否則原始數據並沒有變化
df["Jan Units"] = pd.to_numeric(df["Jan Units"],errors='coerce')
df["Start_date"] = pd.to_datetime(df[['Month', 'Day', 'Year']])df/<code>
pandas 數據類型轉換

<code>df.dtypesCustomer Number             int32
Customer Name object
2016 float64
2017 float64
Percent Growth float64
Jan Units float64
Month int64
Day int64
Year int64
Active bool
Start_date datetime64[ns]
dtype: object# 將這些轉化整合在一起
def convert_percent(val):
"""
Convert the percentage string to an actual floating point percent
- Remove %
- Divide by 100 to make decimal
"""
new_val = val.replace('%', '')
return float(new_val) / 100

df_2 = pd.read_csv("sales_data_types.csv",dtype={"Customer_Number":"int"},converters={
"2016":convert_currency,
"2017":convert_currency,
"Percent Growth":convert_percent,
"Jan Units":lambda x:pd.to_numeric(x,errors="coerce"),
"Active":lambda x: np.where(x=="Y",True,False)
})df_2.dtypesCustomer Number int64
Customer Name object
2016 float64
2017 float64
Percent Growth float64
Jan Units float64
Month int64
Day int64
Year int64
Active bool
dtype: objectdf_2/<code>
pandas 數據類型轉換


分享到:


相關文章: