【Python】數據清洗之黑白雙俠——numpy&pandas庫

  我們分別看看numpy和pandas在數據處理中都有哪些突出的優缺點,不過大部分內容我會直接插入代碼塊,在代碼塊中進行解釋。

Numpy

  numpy庫有比python基礎函數更高級的多維數組數值計算與處理的方法及函數。

###1  一維數組
import numpy as np
#dir(np)#查看有哪些下屬

# 創建一維數組
a=np.array([1,2,3,4])
#a[1:3]

np.array(range(1,11,5))

np.arange(1,11,1)#與range 的區別
np.arange(10,0,-0.9)#左包含右不包含

np.linspace(0,9,3,endpoint=True)#生成一個數組,分組數據  endpoint是否包含結束值

###2  二維數組
np.array([[1,2,3],
          [4,5,6]])
np.array([["張三","男",23],["張三","女",18]],
         dtype=object)#輸入的數據類型 dtype 儘可能的一致,行列整潔

###3  數組屬性
a=np.array([1,2,3])
b=np.array([[1,2,3],
         [4,5,6]])

a.ndim
b.ndim

a.shape
b.shape

a.size
#b.size

a.dtype
b.dtype

a.itemsize#每個元素佔的字節
b.itemsize#每個元素佔的字節

b.itemsize*b.size

###4  缺失值問題
np.nan,None 的區別

###5  特殊數組的 快速生成
np.zeros((3,4))#生成全0 數組
np.zeros(5)
np.ones((4,4))
np.eye(5)
np.diag([1,2,3,4])#對角線矩陣
np.full((2,3),'zgl')#自定義元素數組
np.full((2,3),np.array([1,2,3]))#
np.empty((2,1))#隨機元素填充 一般不用此函數來生成數組

x = np.arange(6).reshape(2,3)
x=np.array([[1,2,np.nan],[2,np.nan,4]])
np.argwhere(np.isnan(x))#獲取缺失值的位置  只適用於 np.nan 數值型

###6  隨機數組的生成
np.random.seed(100)#設定隨機數種子
np.random.rand(3,4)#(0,1)間的3行4列的隨機數組
np.random.random(10)
np.random.random((3,4))

np.random.uniform(10,50,(3,4))#間的3行4列的隨機數組
np.random.randn(3,4)# N  ~  (0,1)間的3行4列的隨機數組  標準正太分佈
np.random.randint(3,10,(3,4))#(0,1)間的3行4列的隨機數  整數
np.random.choice(3,10,2)

###7  數組排序
a=np.array([1,3,0,5])#返回變量值索引
np.argsort(a)

np.sort(a)#返回值
b=np.array([[1,3,5],[2,1,3],[0,5,1]])
b

np.argsort(b,axis=0)#默認按列排序
np.argsort(b,axis=1)
np.sort(b,axis=1)#每行(列)排序
np.sort(b,axis=0)  

b=np.array([[1,5,3],[2,1,3],[0,5,1]],dtype=object)
b

b1=sorted(b,key=lambda x:x[2],reverse=True) #與numpy 的區別
b1


students = np.array([['john', 'A', 15],
                     ['jane', 'B', 2],
                     ['dave', 'B', 10]],dtype=object)
students
# 按年齡排序 
#sorted(students, key=lambda s: s[2], reverse=True)       # 按降序


sorted(students, key=lambda x: x[2])     

###8  重塑數組
np.arange(12).reshape(3,4)
np.arange(6).reshape(1,-1)
np.arange(6).reshape(-2,2)
np.arange(12).reshape(3,-1)
a.ravel(order=True)

a=np.array([[1,4],[3,4]])
np.tile(a,3)
a.ravel()

###9  數組索引
a1=np.array([["張三","男",23],["李四","女",180],["李紅","女",170]])
a1

a1[0:2]
a1[[1,3],[0,2]] 錯誤

a1[[0,1],:] [:,[0,1]]
a1[1:3,[0,2]]

###10  布爾索引
a=np.array(["a","b","a","a"])
a

b[a=='a']

c=np.random.rand(3,4)
c
c[c[:,0]<0.5]

dd=c[  (c[:,0]<0.8) ]
dd

ins=np.array([["張三","女",180],["李四","男",170],["李紅","女",160]],dtype=object)
ins
ins[(ins[:,1]=='女') &  (ins[:,2]>170) ]

###11  二維數組的合併
b1=np.array([[1,2,3],[4,5,6]])
np.concatenate((b1,b1),axis=0)
np.concatenate((b1,b1),axis=1)#一維數組的合併不用設定橫縱合併

###12  運算
a0=np.array([[1,1,1],
             [2,2,2]])
b0=np.array([[3,3,3],
             [4,4,4]])
a0*b0 #元素對元素的積也稱爲哈達馬積(Hadamard product)
#注意這裏要和矩陣的乘法相區別。

a01+a02 # 廣播運算 高維的後緣維度 == 低維維度的概念

#某個維度的軸長爲1
a=np.array([[0,0,0],
            [1,1,1],
            [2,2,2],
            [3,3,3]])
b=np.array([[1],
            [2],
            [3],
            [4]])
a+b

###13  通用函數
np.add、np.maximun、np.minimun等

###14  ndarray實例的常用方法
#轉置
np.array([1,2,3]).T #一維數組轉置之後還是自身

a=np.array([[1,2,3]]).T #a的shape是(1,3)
a

a.T #轉置之後變成了(3,1)

a=np.arange(12).reshape(3,4) #shape爲(3,4)
a
a.T #shape爲(4,3)

#transepose方法
a=np.arange(12).reshape(3,4)
a.transpose(1,0)

# astype方法
a=np.arange(12).reshape(3,4)
a.astype(np.float)

a.astype("str")
#a.astype(np.str_)
#a.astype("U")
#上面這幾個命令都可以

a=np.array([1,2,3,np.nan])
a.astype("str")

#tolist方法
a=np.array([1,2,3,np.nan])
a.tolist()

###15  np.char模塊下面的字符串函數
a=np.array(["a","b","c"])
b=np.array(["1","2","3"])

c=np.array(["1","2",np.nan])
d=np.array(["1","2",None])
np.char.add(b,a)
np.char.upper(a)

a1=np.array(["a b c","d e f"])
a1=np.char.split(a1,sep=" ")
a1.shape

###16  線性代數的矩陣運算
#矩陣的行列式
a=np.random.randint(1,6,(4,4))
np.linalg.det(a) #只有方陣才能求行列式

#矩陣的逆矩陣
a=np.random.randint(1,6,(4,4))
np.linalg.inv(a) #只有方陣才能求逆矩陣

###17  特殊元素構成的數組
=np.array([{1,2},{3,4},{5,6}],dtype="object")
#注意這裏dtype="object"可以省略。
#a是一個一維數組,它的shape是(3,)
a=np.array([{1,2},{3,4},{5,6}])
a 
a.ndim

#17.1  二維數組的協方差矩陣
import numpy as np
data1=np.random.rand(2,4)
data1

np.cov(data1) #每一行是一個變量,如果你的變量是列,就要記得轉置。
data2=np.array([[1,2,3],
               [3,4,5]])
sum(data2,2)
np.sum(data2,1)

a = np.array([[1, 2, 3], [4, 5, 6]])
a.size

Pandas

  Pandas是Numpy的改進升級版,它解決了numpy的問題,提供了更高級數據框對象等數據結構及方法。

###1. 導入相關的庫
import pandas as pd
import numpy as np

###2.Series對象
d=pd.Series(np.random.rand(5),index=list("abcde"))
c[0::2]
d["a":"c"]
d[(d>0.2) & (d<0.5)]

a=pd.Series(["1","2","a"])
pd.to_numeric(a,errors="coerce")

def f1(x):
    try:
        v=float(x)
    except:
        v=np.nan
    return v
a.map(f1)

a.map(lambda x:x+2)

###3.數據框對象
data3=pd.DataFrame([[1,2,3],[4,5,6]],columns=list("abc"))
data2=pd.DataFrame({"a":np.random.rand(10),"b":np.random.rand(10)})
data1=pd.DataFrame(np.random.rand(5,3),columns=["a","b","c"])
pd.read_csv("individual1.csv",encoding="GBK")

a=pd.read_excel("chapter3_1.xls",sheet_name="Sheet1",nrows=10,skiprows=1,header=0)
a.info()
a.head(3)
a.tail()
a.shape
a.columns
a.index
a.T

data1=pd.DataFrame(np.arange(12).reshape(3,4),
                   columns=["a",1,"c","e"],index=list("abc"))
data1[0:2]
data1[["a","c"]]
data1.loc[:,"x1":"x2"]
data1.loc[["a","b"],["x1","x2"]]
data1.iloc[0:2,:]
data1.ix[0:2,"x1":"x2"]
data1[(data1["x1"]>0.5) | (data1["x2"]<0.5)]

data1.pop("x1")
data1.drop(columns=["x2",'x1'],axis=2)#,inplace=False) index=''

data1["z1"]=10
data1["x2"].rank(method="first",ascending=False)
data1["z2"]=data1["x2"]**2
data1["z3"]=data1["x2"].map(lambda x:x**2)
data1.apply(lambda x:max(x.x2,x.x3),axis=1)

a=pd.DataFrame(
	np.random.randint(60,100,(6,3)),columns=["語文","數學","英語"])
a.apply(np.sum,axis=1)

data1.applymap(lambda x:x+2)
data1.rename(columns={"x1":"z1","x2":"z2"})

data1.to_csv("test.csv",index=False)

###3.1 表的合併
pd.concat([data1,data2],axis=0,ignore_index=True)
data1.append(data2,ignore_index=True)

pd.concat([data1,data2],axis=1)#,ignore_index=True)
data1=pd.merge(data1,data2,
               left_on="pid",right_on="pid",
               how="outer",suffixes=("_1","_2"))

###3.2字符串數據還原,缺失值填充,刪除無用列,整合數據表
# x.zfill()  +  map 方法 填充還原‘pid’數據
# 不 賦值給原數列 ,那麼 不改變原實例
individual1["pid"]=individual1["pid"].astype(str).map(lambda x:x.zfill(7))
individual1.head()

# 自定義一個函數 用於還原填充原數據
def f1(x):
    return "0"*(7-len(str(x)))+str(x)
individual2["pid"]=individual2["pid"].map(f1)
# pd.merge 橫向合併,指定表連接的字段,指定連接類型,指定重複列的標籤
data1=pd.merge(individual1,individual2,left_on="pid",
         right_on="pid",how="outer",suffixes=("_1","_2"))
data1.head()

# 當fid_1 缺失值時,用fid_2 填充,,,inplace=True表示在原數據上修改
data1["fid_1"].fillna(data1["fid_2"],inplace=True)

# 刪除 無用的 列
data1.drop(columns=["fid_2"],errors="ignore",axis=1,inplace=True)

#更改 修改更新後的列的列名
data1.rename(columns={"fid_2":"fid","fid_1":"fid"},inplace=True)
# 年齡_2 有缺失,用年齡_1 的值來換
data1["年齡"]=data1["年齡_2"].fillna(data1["年齡_1"])
# 刪除 無用的那兩列
data1.drop(columns=["年齡_1","年齡_2"],inplace=True)
#導出數據文件
data2.to_excel("整理好後的數據.xlsx",index=False)

###4.數據框排序
data1=pd.DataFrame(np.random.rand(4,3),
                   columns=["x1","x2","x3"],index=np.arange(4)[::-1])

data1.sort_values(by="x1",ascending=True)
data1.sort_values(by=["x1","x2"],ascending=[True,False],inplace=True)
data1.sort_index(ascending=True,inplace=True)

###5. 變量的描述
data1.describe()# 無參數默認描述數值數據 應該處理好 數據的真實數據類型  eg此處的pid
data1.describe(include=["object"])# 指定描述的數據類型
data1.describe(exclude=["object"],percentiles=[0.1,0.2])
#指定不描述的類型, 添加要描述的統計量percentiles=[0.1,0.2]

###6.查看唯一值 可以用於查重
# 查看唯一值
data1["性別"].unique()

# 查看唯一值並且分別計數
a=data1["性別"].value_counts()

###7.groupby 方法 分組
data1.groupby(data1["性別"])
data1.groupby([data1["性別"],data1["地域編碼"]])
group.max()
# 單個變量
data1["年齡"].groupby(data1["性別"]).max()
data1["年齡"].groupby(data1["性別"]).quantile(0.2)
# 多個變量 通常不這樣用
data1.groupby(data1["性別"]).max()

# .describe() 不同性別 的 年齡 情況
data1["年齡"].groupby(data1["性別"]).describe()
# agg 方法指定要描述的統計量
data1[["年齡","受教育程度"]].groupby(data1["性別"]).agg(["mean","max","min"])

###8.transform 返回的對象 與原數據的索引保持一致  填充缺失值
data1["年齡"].groupby(data1["性別"]).transform(lambda x:x.count())
data1["年齡"].groupby(data1["性別"]).transform(np.mean)

def f1(x):
    return x.count()
data1["年齡"].groupby(data1["性別"]).transform(lambda x:f1(x))
data1["年齡"].groupby(data1["性別"]).transform(f1)

###8.數據透視表
data1.pivot_table(values=["年齡","受教育程度"],
                  index=["性別","地域編碼"],
                 aggfunc={"年齡":[np.mean,np.max],"受教育程度":[np.median]})

###9.變量與索引的相互轉化
temp=data1.set_index(["fid","pid"],drop=True)
# 還原變量索引轉換,若無變量索引,則將真實索引轉換爲變量
temp.reset_index()
temp.reset_index().reset_index()

###10.將數值變量進行離散化處理
pd.cut(data1["年齡"],3)
pd.cut(data1["年齡"],[0,45,59,74,89,120],
       labels=["青年","中年","老年前期","老年","長壽老人"])
pd.cut(data1["年齡"],[0,45,59,74,89,120],
       labels=[1,2,3,4,5])

# pd.qcut:用分位數進行分箱
pd.qcut(data1["年齡"],4,labels=[1,2,3,4])

#分箱並計數
pd.qcut(data1["年齡"],4,labels=["青年","中年","老年前期","老年"]).value_counts()

###11.將分類變量轉化爲虛擬變量(pd.get_dummies)
pd.get_dummies(data1["性別"],prefix="性別")
## 將轉換的虛擬變量 合併到  實例數據 ::::  用於分析應選擇一列做參考,並將其從數據中刪除
pd.concat([data1,  pd.get_dummies(data1["性別"]  ,prefix="性別")],axis=1)
##  drop_first=True 默認以第一個虛擬變量爲參考,刪除第一個虛擬變量
pd.concat([data1,
           pd.get_dummies(data1["性別"],prefix="性別",drop_first=True)],
          axis=1)

###12.數據框對象的複製
data2=data1.copy(deep=True)

###13.字符串變量的常用方法
data1.fid.str.len()
data1.fid.str.replace("f","a")
data1.fid.str.count("0")
data1.pid.astype(str).str.zfill(5)
series1=pd.Series(["河北省衡水市","河北省石家莊市","河南省鄭州市"])
series1.str.extract(r"(.+省)")

###14.判斷唯一值
data1=pd.DataFrame([["張三","201",80,90,90],
    ["李四","202",80,90,90],
    ["張三","201",80,90,90]],
    columns=["姓名","學號","語文","數學","英語"])

data1.duplicated()# 判斷是否是重複項  返回布爾值
data1.duplicated(subset=["數學","英語"])# 判斷 指定數列是否是重複項  返回布爾值

#  保留第一個重複值,刪除其他重複數據行記錄
data1.drop_duplicates(subset=["數學","英語"],keep="first")

###15.數據框抽樣
len(data1.sample(frac=0.3)) #設定了抽取樣本比例爲10%,所以抽去了100行。
#data1.sample(frac=0.3)
#data1.sample(frac=0.1)
#replace=False表示無放回抽樣。
#random_state是設定隨機種子,保證每次運行代碼抽取到的樣本一樣。

###16.時間變量的處理
#pd.Timestamp 返回時間戳 對象
pd.Timestamp("2017-01-02T12")#傳入字符串
pd.Timestamp("2017/1/1")
pd.Timestamp(1, unit='s', tz='Asia/Shanghai')
#根據距離紀元的秒數生成時間戳(可設定時區)
#根據距離紀元的秒數生成指定時區的時間,默認是0時區。
pd.Timestamp(2017,1,1,1)
pd.datetime(2017,1,1)
pd.Timestamp(pd.datetime(2001,1,1))
#pd.to_datetime  返回時間戳 對象
pd.to_datetime("2019/08/31",format="%Y/%m/%d",errors="coerce")

pd.to_datetime(1,unit="s")
pd.to_datetime(pd.datetime(2019,8,28))

pd.datetime.now()# 不是正常的時間 格式
import datetime
datetime.datetime.now()# 不是正常的時間 格式
import time
time.localtime()# 不是正常的時間 格式
datetime.datetime.now().timetuple()# 不是正常的時間 格式

###時間戳實例的屬性和方法
a=pd.Timestamp("2017-1-1T12:9:6")
a.year
a.month
a.day
a.hour
a.minute
a.second
a.dayofweek+1
a.time()
a.date()
a.value
a.timestamp()
a.strftime("%Y-%m-%d")
a.strftime("%A")

###計算時差Timedelta實例
a=pd.Timestamp("2019/8/28T15:49:30")
b=pd.Timestamp("2019/8/27T15:30:20")
a-b

cd=pd.Timedelta(days=1,hours=2,minutes=3,
                seconds=4,milliseconds=5,microseconds=6,nanoseconds=7)
cd.total_seconds()
cd.delta
cd.components
cd.components.days
cd.components.milliseconds

### 生成時間戳範圍
a=pd.date_range("2001-1-1",freq="D",periods=10)# 元素爲時間字符串的 時間戳列表
###時間數據 處理 實例
data1=pd.read_excel("上證指數日收盤價數據.xls")
data1.head()
data1.info()
data1.drop(columns=["index"],inplace=True)


data1["year"]=data1["date"].dt.year
data1["month"]=data1["date"].dt.month
data1["day"]=data1["date"].dt.day
data1["dayofweek"]=data1["date"].dt.dayofweek+1

#如何把年月日時間變成年月時間
data1["ym"]=data1["date"].dt.to_period(freq="M")
data1["date1"]=data1.apply(lambda x:pd.Timestamp(x["year"],
                                                 x["month"],x["day"]),axis=1)
pd.to_datetime(data1["datestr"],format="%Y/%m/%d",errors="coerce")
data1["date2"]=pd.to_datetime(data1["num"],unit="s")
data1["date3"]=data1["num"].map(lambda x:pd.Timestamp(x,unit="s",tz="Asia/Shanghai"))

data1["date"]+pd.Timedelta(days=30)

###求變量的滯後一期
data1["p"].shift(1)

###求變量的先導一期
data1["p"].shift(-1)

import math
data2["r"]=data2["p"].map(lambda x :math.log(x))-data2["p1"].map(lambda x:math.log(x))

###日期時間變量用做數據框的索引
data2.index=data2["date"]
data2["p"]["2003-1-8"]
data2["p"]["2003-1"]
data2["p"]["2003-1-1":"2003-1-10"]
data2[(data2.index>"2003-10-1") & (data2["r"]>0)]
data2.to_period(freq="M")

series1=pd.date_range("2003-1-1",freq="D",periods=100)

data1=pd.DataFrame(np.random.rand(100,2),columns=["x1","x2"])
data1.index=series1

data2=data1.asfreq(freq="5D")
data2.asfreq(freq="D").head(10)

data2.asfreq(freq="D",method="pad")

  上面的兩塊代碼區便是numpy、pandas庫在數據清洗中常用的形態了,後期若研究出新的使用方式,會專門補充。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章