Python利用pandas處理資料與分析

konglingbin發表於2024-03-25

pandas 是基於NumPy 的一種工具,該工具是為了解決資料分析任務而建立的。Pandas 納入了大量庫和一些標準的資料模型,提供了高效地操作大型資料集所需的工具。pandas提供了大量能使我們快速便捷地處理資料的函式和方法。簡單地說,你可以把 Pandas 看作是 Python 版的 Excel。
pandas具有以下資料結構:

Series:一維陣列,與Numpy中的一維array類似。二者與Python基本的資料結構List也很相近。Series如今能儲存不同種資料型別,字串、boolean值、數字等都能儲存在Series中。

Time- Series:以時間為索引的Series。

DataFrame:二維的表格型資料結構。很多功能與R中的data.frame類似。可以將DataFrame理解為Series的容器。

Panel(最近的版本已經棄用這個資料結構,所以不做介紹) :三維的陣列,可以理解為DataFrame的容器。

我們本文就來一起總結學習pandas常用資料結構和操作

1 資料結構以及操作——Series
Series 是一種一維陣列,和 NumPy 裡的陣列很相似。事實上,Series 基本上就是基於 NumPy 的陣列物件來的。和 NumPy 的陣列不同,Pandas 的 Series 能存放各種不同型別的物件,Series 能為資料自定義標籤,也就是索引(index),然後透過索引來訪問陣列中的資料。

這裡主要利用pandas從六個方面來對資料進行操作:

1 匯入資料
自我生成資料

pandas 有兩個常用的資料結構:Series 和 DataFrame,可以用來生成你想要的陣列型物件。

pd.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)

pd.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)

外部載入資料

但是,在一般的資料處理分析中,往往自我生成資料情況較少,更多的是匯入資料。pandas提供了一些用於將表格型資料讀取為DataFrame物件的函式。
這裡匯入本次需要的用到的資料(該資料來自天貓爬取的網頁資料,有興趣的可以自己去爬取,這裡只是暫做示例):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data = pd.read_excel("E:/data/tianmao_phone.xlsx")

表1對我們常用的檔案格式進行了總結,其中pd.read_csv()和pd.read_excel()可能會是你今後用得最多的。

這些pandas的解析函式引數較為複雜,具體瞭解可以在pandas官網上自行查閱,或者可以再Jupyter Notebook 中採用help(pd.read_excel)命令查閱。

注:這裡使用的都是小規模的資料(500萬以下),而在現實生活中的資料有時往往跟為複雜(動輒幾個G到TB),pandas在讀取的時候往往就會用到chunsize等引數(可以傳入大小)分塊讀取。
但是,其效率也是低下,所以建議大資料還是用一些適合它的的工具(資料庫等),沒有最好的工具,只有最適合的工具。

2 審閱資料
在成功匯入資料以後,需要對資料進行審閱,目的是,瞭解資料結構、型別、大小等情況。方便理解資料和為後續處理分析打下基礎。

1.檢視前5行(預設前5行,你也可以在括號裡輸入你想要的行數):

data.head()
2.檢視倒數5行:

data.tail()

3.檢視維度資訊:

data.shape

4.檢視每一列的資料格式:

data.dtypes

5.檢視資料表基本資訊(維度、列名稱、資料格式、所佔空間等):

data.info()

6.檢視某一列具體資訊:

#兩種處理效果一樣
data['月銷量']

data.月銷量

7.也可以按索引提取單行或多行數值:

#提取第4行
data.iloc[4]

#提取到第4行
data.iloc[0:4]

#提取所有行,0到4列(也可以反過來)
data.iloc[:,0:4]

#提取第0、2、4行,第3、4列
data.iloc[[0,2,4].[3,4]]

注:資料的選取較為靈活,方法也較多,諸如:data["你要選取的列名稱"],data.loc[],data.iloc[],data.ix[]等等。具體可以上官網瞭解一下他們的區別和作用,這裡就不再繼續詳述了。

8.將資料進行排序

#按銷量的大小進行排序,只取前8行
data.sort_values(by=['累計評價'],ascending=False).iloc[:8,:]
#檢視類別資訊

count_class = pd.value_counts(data['店鋪名稱'],sort=True).sort_index()
print(count_class)

9.檢視基本的統計資訊(最大值、最小值、平均值、中位值、四分位值、標準差等):

data.describe()
1
3 資料預處理
說完對錶中的資料進行簡單的檢視,下面進行對資料進行的最關鍵操作:資料預處理

(1) 資料整合

由於我的資料較為規整,不需要合併和拼接,這裡只是簡單介紹一下原理。

1.pandas.merge可根據一個或多個鍵將不同DataFrame中的行連線起來。SQL或其他關係型資料庫的使用者對此應該會比較熟悉,因為它實現的就是資料庫的join操作。

pandas.merge(left, right, how='inner', on=None,
left_on=None, right_on=None, left_index=False, right_index=False,
sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)

該函式主要用於透過一個或多個鍵將兩個資料集的行連線起來,類似於 SQL 中的 JOIN。典型應用場景是,針對同一個主鍵存在兩張包含不同欄位的表,現在我們想把他們整合到一張表裡。在此典型情況下,結果集的行數並沒有增加,列數則為兩個後設資料的列數和減去連線鍵的數量。

2.pandas.concat該方法相當於資料庫中的全連線(UNION ALL),可以指定按某個軸進行連線,也可以指定連線的方式join(outer,inner 只有這兩種)。與資料庫不同的是concat不會去重,要達到去重的效果可以使用drop_duplicates方法。

pandas.concat(objs, axis=0, join='outer',
join_axes=None, ignore_index=False, keys=None,
levels=None, names=None,verify_integrity=False, sort=None, copy=True)

軸向連線 pd.concat()只是單純的把兩個表拼在一起,這個過程也被稱作連線(concatenation)。這個函式的關鍵引數應該是 axis,用於指定連線的軸向。在預設的 axis=0 情況下,pd.concat([data1,data2]) 函式的效果與 data1.append(data2) 是相同的;而在 axis=1 的情況下,pd.concat([data1,data2],axis=1) 的效果與pd.merge(data1,data2,left_index=True,right_index=True,how='outer') 是相同的。可以理解為 concat 函式使用索引作為“連線鍵”。

3.join方法提供了一個簡便的方法用於將兩個DataFrame中的不同的列索引合併成為一個DataFrame。

DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
1
其中引數的意義與merge方法基本相同,只是join方法預設為左外連線how=left。
4.DataFrame.combine_first(other) 可以將重複資料拼接在一起,用一個物件中的值填充另一個物件中的缺失值。

5.update.如果要用一張表中的資料來更新另一張表的資料則可以用update來實現

DataFrame.update(other, join='left', overwrite=True, filter_func=None, raise_conflict=False)
1
注:使用combine_first會只更新左表的nan值。而update則會更新左表的所有能在右表中找到的值(兩表位置相對應)。

具體瞭解可以在pandas官網上自行查閱,或者可以再Jupyter Notebook 中採用help()命令查閱。

(2) 資料清洗

資料整理

1.字串處理

原始資料中,有很多字串型別的資料,不便於分析,利用字串函式對資料進行處理。

#將“收藏”字串中的數值型資料取出來
data['收藏']=data['收藏'].str.extract('(\d+)')

#同理“庫存”只要資料
data['庫存']=data['庫存'].str.extract('(\d+)')

#同理“天貓積分”只要資料
data['天貓積分']=data['天貓積分'].str.extract('(\d+)')

#“現價”中含有區間值,進行拆分,並取最低價
data['現價']=data['現價'].str.split('-',expand=True)[0]

#同理,“原價”拆分,與“現價”保持一致
data['原價']=data['原價'].str.split('-',expand=True)[0]


2.資料型別處理

將處理完的字串資料,轉換成有利於後續分析的資料。

#時間序列處理
data['當前時間']=pd.to_datetime(data['當前時間'],format='%Y%m%d')

#將時間序列設定為索引並按照索引進行排序
data=data.set_index(data['當前時間']).sort_index()

#由於月銷量資料帶有字串,所以需要將字串替換,並最終轉化為數值型
data['月銷量']=data['月銷量'].str.replace('萬','0000')
data['月銷量']=data['月銷量'].str.replace('+','')
data['月銷量']=data['月銷量'].str.replace('.','').astype(np.float64)

#其他資料型別處理

data['現價']=data['現價'].astype(np.float64)

data['原價']=data['原價'].astype(np.float64)

data['收藏']=data['收藏'].astype(np.float64)

data['庫存']=data['庫存'].astype(np.float64)

data['天貓積分']=data['天貓積分'].astype(np.float64)


注:在處理資料進行格式轉換時,有時object無法轉換成int64或者float64,這時就需要先處理內部格式,再進行轉換。如:
data['orginal_shop_price']=data['orginal_shop_price'].str.replace(",",'').astype(np.float64)

缺失值處理:

1.查詢缺失值。看那些列存在缺失值:

data.isnull().any()
1
2.定位缺失值。將含有缺失值的行篩選出來:

#篩選出任何含有缺失值的資料
data[data.isnull().values==True]

#統計某一列缺失值的數量
data['現價'].isnull().value_counts()

#篩選出某一列含有缺失值的資料
data[data['原價'].isnull().values==True]

3.刪除缺失值:

data.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)`

#刪除月銷量中的缺失值
data.dropna(axis=0,subset=["月銷量"])

可以利用subset和thresh引數來刪除你需要刪除的缺失值,inplace則表示是否在原表上替代。

4.填充缺失值:
固定值填充:

data.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)
1
#利用月銷量的均值來對NA值進行填充
data["月銷量"].fillna(data["月銷量"].mean())

#利用月銷量的中位數來對NA值進行填充
data["月銷量"].fillna(data["月銷量"].median())

#對於一些商品的現價和原價沒有的資料,可採用現價填充原價,原價填充現價。
data["現價"]=data["現價"].fillna(data["原價"])
data["原價"]=data["原價"].fillna(data["現價"])

當然,缺失值的處理方法遠不止這幾種,這裡只是簡單的介紹一般操作,還有其他更高階的操作,比如:隨機森林插值、拉格朗日插值、牛頓插值等等。針對這些高難度的插值方法,有興趣可以自我去了解了解。

重複值處理

定位重複值:

#找出"店鋪名稱"存在重複的資料
data[data.duplicated(subset=["店鋪名稱"], keep='first')]

刪除重複值:

#刪除“店鋪名稱”存在重複的資料
data.drop_duplicates(subset=["店鋪名稱"], keep='first', inplace=False)

異常值處理:

在進行異常值處理之前,需先進行異常值檢驗,比較常用的有兩種方法:

資料服從正態分佈,採用3σ原則。
資料不服從正太分佈,採用箱線圖檢驗。
3σ原則:
#插入一列three_sigma又來表示是否是異常值
data['three_sigma'] = data['月銷量'].transform( lambda x: (x.mean()-3*x.std()>x)|(x.mean()+3*x.std()<x))

#篩選出目標變數的異常值
data[data['three_sigma']==True]

#保留正常的資料
correct_data=data[data['three_sigma']==False]

箱線圖處理異常值:

#定義一個下限
lower = data['月銷量'].quantile(0.25)-1.5*(data['月銷量'].quantile(0.75)-data['月銷量'].quantile(0.25))

#定義一個上限
upper = data['月銷量'].quantile(0.25)+1.5*(data['月銷量'].quantile(0.75)-data['月銷量'].quantile(0.25))

#重新加入一列,用於判斷
data['qutlier'] = (data['月銷量'] < lower) | (data['月銷量'] > upper)

#篩選異常資料
data[data['qutlier'] ==True]

#過濾掉異常資料
qutlier_data=data[data['qutlier'] ==False]

細心的你可能會發現,採用兩種方法來處理異常資料的結果往往是不同的,箱線圖法更為嚴格(有興趣的話,你可以去了解了解其中的原理)。

多餘行/多餘列刪除

data.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')
該操作主要用於不需要的行(預設刪除行)或者列進行刪除,從而有利於資料精簡。

(3) 資料變換
資料變換主要有以下幾點內容:

1.簡單函式變換。例如對資料開方、平方、取對數、倒數、差分、指數等。目的是為了後續分析提供想要的資料和方便分析(根據實際情況而定)。

#由於“累計評價”的值太大,我們新增一列對“累計評價”取對數處理
data['對數_累計評價']=np.sqrt(data['累計評價'])

#插入一列,計算“優惠力度”
data['優惠力度']=data1['現價']/data1['原價']

2.資料標準化。資料標準化是為了消除資料的量綱影響,為後續許多演算法分析必要條件。常見的標準化方法很多,這裡只是簡單介紹一下:
Min-Max標準化

#使不使用函式,根據你的理解都可以,這裡使用函式
data['標準化月銷量']=data.月銷量.transform(lambda x : (x-x.min())/(x.max()-x.min()))

Z-score標準化法

data['Z_月銷量']=data['月銷量'].transform(lambda x : (x-x.mean())/x.std())
1
3.資料離散化處理。連續值經常需要離散化或者分箱,方便資料的展示和理解,以及結果的視覺化。比如最常見就是日常生活中對年齡的離散化,將年齡分為:幼兒、兒童、青年、中年、老年等。

#新增一列,將月銷量劃分成10個等級
data['data_cut']=pd.cut(data['月銷量'],bins=10,labels=[1,2,3,4,5,6,7,8,9,10])

#新增一列,將月銷量劃分成10個等級
data['data_qcut']=pd.qcut(data['月銷量'],q=10,labels=[1,2,3,4,5,6,7,8,9,10])

這兩種都是對資料進行離散化,但透過結果仔細一看,你會發現,這兩者的結果是不同的。說簡單點就是,一個是等距分箱,一個是等頻分享(分位數分箱),往往後者更常用。

(4) 資料精簡
資料精簡在資料分析和資料探勘中至關重要,資料探勘和分析的往往是海量資料,其海量特徵主要體現在兩個方面:第一,樣本量龐大;第二,變數個數較多。海量資料無疑會影響建模的效率,為此主要的應對措施有:
1.壓縮樣本量。主要是指隨機抽樣
2.簡約變數值。主要是指離散化處理
3.變數降維。主要是將許多變數用少數變數來分析(諸如因子分析等)

變數的離散化處理前面已經介紹,這裡從隨機抽樣入手。關於變數降維,後續關於演算法的學習在具體介紹。

  #隨機不重複抽取100行資料樣本
  data.sample(n=100)
關於隨機抽樣函式如下:

sample(n=None, frac=None, replace=False, weights=None, random_state=None, axis=None)
n和frac作用是相同的,n是抽樣個數,frac是抽樣比例(浮點數);
replace:是否為有放回抽樣,取replace=True時為有放回抽樣;
weights這個是每個樣本的權重,具體可以看官方文件說明。

4 資料分析
終於來到了資料分析環節,前面所做的工作全是為了資料分析和資料視覺化做準備。這裡本文只是進行一些簡單的資料分析,關於模型啊,演算法啊……這些,這裡不做介紹,在掌握這些簡單的分析之後,可以去理解更高深的分析方法。
(1) 描述性分析

1.集中趨勢
表示資料集中趨勢的指標有:平均值、中位數、眾數、第一四分位數和第三四分位數。

#透過定義一個函式,來檢視資料的集中趨勢
def f(x):
    return pd.DataFrame([x.mean(),x.median(),x.mode(),x.quantile(0.25),x.quantile(0.75)],
      index=['mean','median','mode','Q1','Q3'])

#呼叫函式
f(data['月銷量'])

2.離散程度
表示資料離散程度的有:方差,標準差,極差,四分位間距。

#透過定義一個函式,來檢視資料的離散程度
def k(x):  
    return pd.DataFrame([x.var(),x.std(),x.max()-x.min(),x.quantile(0.75)-x.quantile(0.25)],
        index=['var','std','range','IQR'])

#呼叫函式
k(data['現價'])

2.分佈形態
表示資料分佈的有:偏度和峰度。

def g(x):
  return pd.DataFrame([x.skew(),x.kurt()],
    index=['skew','kurt'])

(2) 相關性分析
研究兩個或兩個以上隨機變數之間相互依存關係的方向和密切程度的方法。線性相關關係主要採用皮爾遜(Pearson)相關係數r來度量連續變數之間線性相關強度;r>0,線性正相關;r<0,線性負相關;r=0,兩個變數之間不存線上性關係,但是,並不代表兩個變數之間不存在任何關係,有可能是非線性相關。

#相關係數矩陣
data.corr()

#協差陣
data.cov()

#任意兩列相關係數
data['月銷量'].corr(data['累計評價']

#因變數與所有變數的相關性
data.corrwith(data['月銷量'])

5 pandas資料視覺化
資料視覺化的作用很多,而最常用的一般有兩種功能:其一是對原始資料的探索性分析(EDA),其二是對結果資料的資料分析結果呈現。

  data_plot=data.groupby(by="店鋪名稱").agg({'月銷量':sum})

  #下面的程式碼與上面的效果等同

  data.groupby(by='店鋪名稱')['月銷量'].sum()

data_plot.unstack().sort_values(ascending=False).plot(kind='bar', figsize=(20, 5))


參考:https://blog.csdn.net/qq_40195360/article/details/84570503

https://www.cnblogs.com/liulinghua90/p/9935642.html(Python利用pandas處理Excel資料的應用)

https://blog.csdn.net/qq_42415326/article/details/89678833?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-89678833-blog-54632492.235^v43^pc_blog_bottom_relevance_base9&spm=1001.2101.3001.4242.1&utm_relevant_index=3

相關文章