資料分析-pandas資料處理清洗常用總結

weixin_34413357發表於2018-04-12

利用pandas包進行資料分析時常見的操作有:

  • 1.建立物件
  • 2.檢視物件
  • 3.選擇
  • 4.缺失值處理
  • 5.相關操作
  • 6.合併
  • 7.分組和分段
  • 8.軸轉換和資料透視表
  • 9.時間序列
  • 10.匯入和儲存資料

一、建立物件

  • 建立Series
  • 建立DataFrame
  • 檢視不同列的資料型別
  • 改變索引列名
    1.通過傳遞一個 list 物件來建立一個 Series
s=pd.Series([1,2,3,np.nan,6,8])
s

11098258-6ef1a293a1d41ae4.png

2.通過傳遞一個 numpy array,時間索引以及列標籤來建立一個 DataFrame
numpy.random.randn()是從標準正態分佈中返回一個或多個樣本值。
numpy.random.rand()的隨機樣本位於[0, 1)中。
np.random.randint(0,7,size=10)生成0到7的隨機整數

dates=pd.date_range('20130101',periods=6)
df=pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))
df
11098258-3d1c7f17ba01a58a.png

index和columns也可以在DataFrame建立後指定:

df.index=pd.date_range('20130101',periods=df.shape[0])
df.index=pd.date_range('20130101',periods=len(df))

另外,還可以指定某一列為索引

df = df.set_index('A', drop = True)

通過字典物件來建立一個 DataFrame

df2=pd.DataFrame({'A':1.,
                 'B':pd.Timestamp('20130102'),
                 'C':pd.Series(1,index=list(range(4)),dtype='float32'),
                 'D':np.array([3]*4,dtype='float32'),
                 'E':pd.Categorical(['test','train','test','train']),
                 'F':'foo'})
df2
11098258-3dbfd751a746f806.png

另外,在原有資料df的基礎上,可以建立一個新的資料框df3

df3=pd.dataframe()
df3['min']=df.min()
df3['max']=df.max()
df3['std']=df.std()
df3

或者按行進行彙總統計建立一個新的資料框df4

df4=pd.dataframe()
df4['min']=df.min(axis=1)
df4['max']=df.max(axis=1)
df4['std']=df.std(axis=1)
df4

軸為0的時候是對列的資料進行統計運算,比如shape[0]是行的個數,相當於一個完整的列有多少資料,df.min(axis=0),求每一列的最小值。軸為1是對行的資料量進行統計。
3.檢視不同列的資料型別

df2.dtypes
11098258-b4e49590ad3bd339.png

4.改變索引列名

df.rename(index=lambda x:x+5,columns={'A':'newA','B':'newB'})
11098258-54c4d41724bd9111.png

二、檢視資料

  • 檢視頭尾的行資料
  • 顯示索引、列、底層的資料
  • 統計
  • 轉置
  • 按軸排序
  • 按值排序
  • 檢視最大值的索引
  • 格式化輸出format
    1.檢視頭尾的行資料
df.head()
11098258-ddf2be8ed8445481.png
df.tail(3)

11098258-391e974690f0719f.png

2.顯示索引、列、底層的資料
df.index
df.columns
df.values
11098258-ec897723f89ed4c3.png

11098258-fef98ae782bb60c1.png

11098258-e84881d0350401ad.png

注意,list(df)顯示的是columns
3.統計
檢視資料框的行數與列數:(shape[0]是行數shape[1]是列數)

df.shape
11098258-aff0cf967b78e96d.png

檢視資料框 (DataFrame) 的索引、資料型別及記憶體資訊:

df.info()
11098258-a9ee416da47cae02.png

統計每一列非空個數

t.count()
11098258-bc5e91679f98f812.png

統計某列有多少個不同的類用.nunique()或者len(set()),(統計某列不同類對應的個數用value_counts(),後面相關操作中會提到)

df.A..nunique()
len(set(df.A))

統計某列有哪些不同的類(使用value_counts()也可以顯示,同時會顯示各個類的個數)

df.A.unique()

統計某列是否有重複資料

df.A.is_unique

對於資料型別為數值型的列,查詢其描述性統計的內容:

df.describe()
11098258-a03b5213487a2102.png

統計相關係數

df.corr()

4.轉置

df.T
11098258-0c06bf6295eab111.png

5.按軸排序
df.sort_index(0) 按行名排序
df.sort_index(1) 按列名排序

df.sort_index(axis=1,ascending=False)
11098258-b4f887e23e10460d.png

6.按值排序
按行的值排序:

df.sort_values(by='20130101',axis=1)
11098258-61d53ca74b3a71d5.png

按列的值排序:

df.sort_values(by='B')
11098258-ff2afbf83d8aeeec.png

按順序進行多列降序排序

df.sort_values(['A','B'],ascending=False)

7.檢視最大值的索引

df.idxmax(0)    #顯示所有列最大值所對應的索引
df.A.idxmax(0)   #顯示A列中最大值對應的索引

8.格式化輸出format
“格式限定符”(語法是'{}'中帶:號),可以print相應格式的資料

print('{:.2%}'.format(0.12354))
11098258-2068921ff3a80e8d.png

金額千位分隔符

print('{:,}'.format(123456789))
11098258-e12195b27c5a8caf.png
print('{:.2f}'.format(31.31412))
11098258-26221a53d11db003.png

三、選擇

  • 直接獲取資料
  • 通過標籤進行選擇 .loc[]
  • 通過位置進行選擇 .iloc[:,:]
  • 布林索引
  • 設定賦值
    1.直接獲取資料(用於獲取整行或者整列的資料),此處注意列名一定要大小寫對應,否則無法取出資料
df['B']
df.B
11098258-1ab62fbc51eb7185.png

選擇兩列

df[['A','B']]

通過切片獲取資料

df[0:3]
df['20130101':'20130103']
11098258-3fd36c51ce1cfa59.png

2.通過標籤進行選擇 .loc[]
標籤的優點是可以多軸交叉選擇(注意:iloc內部只能單獨使用行標籤選擇行資料,選擇某一列標籤時前面需加:,):

df.loc[dates[0]]
11098258-c8b50d1618309899.png

位置加標籤(注意只能用:,不能使用類似0:2的切片):

df.loc[:,['A','B']]
11098258-156b0540e24fd517.png

標籤加標籤:

df.loc['20130101',['A','B']]
11098258-31c323c928e13f83.png

獲取一個標量:

df.loc['20130101','A']

11098258-a457479599c15427.png

3.通過位置進行選擇 .iloc[:,:]
通過傳遞數值進行位置選擇(選擇的是行),特別是選擇單行的時候(注意:iloc內部只有一個值得時候是選擇的行,選擇某一列時列號前面需加:,),另外-1代表最後一列:

df.iloc[3]
11098258-79b6777cbc528d4b.png

選取除了最後三列之外的資料

df.lioc[:,:-3]

通過數值進行切片 位置加位置(區別於loc之處)

df.iloc[1:3,1:3]
11098258-64b5bb8cf657b381.png

通過制定一個位置的列表:

df.iloc[[1,2],[2,3]]
11098258-458b523a4aa66739.png

對行、列進行切片:

df.iloc[[0,1],:]
df.iloc[:,[0,1]]
11098258-0cce1f804822907a.png

11098258-cec2bb3fd161eb76.png

獲取特定的值:

df.iloc[1,1]
11098258-d2716c64090d3221.png

4.布林索引
使用一個單獨列的值來選擇資料:

df[df.A>0]
11098258-40405d259c85eddc.png
df[df>0]
11098258-5251e9d0efa6a16f.png

選擇A列中以a開頭的行或列(假設此處的A列是字串型資料)

df[df.A.str.startswith('a')]

使用 isin()方法來過濾:

df['E']=['one','one','two','there','four','there']
df[df.E.isin(['two','four'])]
11098258-749c75324f558da6.png

5.賦值
①通過標籤設定新的值

df.loc['20130101','A']=1
df
11098258-6b446363275cef32.png

如果賦值的標籤不存在,則產生新的列(行),未賦值的位置用空值填充

t.loc['20130101','H']=3
t
11098258-b33d6e2da5c9c664.png

②通過位置設定新的值

df.iloc[0,0]=2
df
11098258-0bcab0b63ccb56fb.png

③設定整列值(len可以求表格資料的行數):

df.loc[:,'D']=np.array([3]*len(df))
df

或者

df['D']=np.array([3]*len(df))
df
11098258-67a82f1b90e35650.png

④通過布林索引賦值

df2=df.copy()
df2[df2>0]=-df2
df2     #全部轉化為負數
11098258-68f1a75e37f67939.png

四、缺失值處理

  • 刪除列的方法
  • 去掉包含缺失值的行,不改變原來的值
  • 對缺失值進行填充
  • 對資料進行布林填充


    11098258-a9bd27b5b55ca832.png

    檢視每一列有多少缺失值:

df.isnull().sum()

檢視每一列有多少完整的資料

df.shape[0]-df.isnull().sum()

1.刪除列的方法:

df.drop(df.columns[4],axis=1,inplace=True)  #不知道列名時
df.drop(‘E’,axis=1,inplace=True)   #根據列名刪除

del df['E']

2.去掉包含缺失值的行,不改變原來的值

df.dropna()   #不返回df還是原值
df.dropna(how='all')   #刪除所有均為空值的行
df.dropna(inplace=True)   #返回刪除後的
11098258-10f493cc0e11f798.png

移除資料框 DataFrame 中包含空值的列

df.dropna(axis=1)
11098258-34860fca3290e17f.png

3.對缺失值進行填充(如果填充後需要儲存,需加inplace=True):

df.fillna(value=5)
11098258-6b1935e040c7946e.png

將所有空值替換為平均值

df.fillna(df.mean())
11098258-cedf840ded3ce8c3.png

4.對資料進行布林填充

pd.isnull(df)
11098258-d3f7112dc26f486b.png

五、相關操作

  • 統計行列平均值
  • Apply – 對資料應用函式
  • 計數 value_counts()
  • 字串大小寫轉換
  • 資料型別轉換
  • 替換
    1.統計行列平均值
    按列統計平均
df.mean()
11098258-4cb7fe9cc4d59109.png

對平均值取整

round(df.mean())

按行統計平均

df.mean(1)

11098258-5e558257cede72a5.png

2.Apply – 對資料應用函式
其中注意臨時函式lambda的使用

df.apply(lambda x:x.max()-x.min())
11098258-901f4819ffbfc2dd.png
df.apply(np.mean)   按行統計axis=1
11098258-af87fcbe6c1c6a4f.png
df.apply(np.max,axis=1)
11098258-cacd94df20e6bf49.png

另外可以通過def 定義函式,再使用apply,例如下面資料的第一列,時間為2061年,存在明顯錯誤,可以通過建立函式去修復這個錯誤

data = pd.read_table(path6, sep = "\s+", parse_dates = [[0,1,2]]) 
data.head()
11098258-d9a65cc15a0164e9.png
import datetime
def fix_century(x):
    year = x.year - 100 if x.year > 1989 else x.year
    return datetime.date(year, x.month, x.day)
data['Yr_Mo_Dy'] = data['Yr_Mo_Dy'].apply(fix_century)
data.head()
11098258-369359fbe93639e3.png

3.計數 value_counts()

s=pd.Series(np.random.randint(0,7,size=10))
s.value_counts()
11098258-6c0c96c9d39043ba.png

DataFrame檢視某一列類別資料各類的個數:

df2.E.value_counts()
11098258-e2e190e9822eaabd.png

DataFrame檢視所有列的各類統計個數

df2.apply(pd.Series.value_counts)
11098258-89745cd19517696d.png

4.字串大小寫轉換

s=pd.Series(['One','Two'])
s.str.lower()
11098258-b0231b9052b7e2a8.png

5.將DataFrame的格式轉化為浮點數

df.astype(float)
11098258-6efaf2f9314c9b3d.png

6.替換

df.replace(4,'one')
11098258-ee3d0ca116769217.png

六、合併

  • concat (不通過鍵值之間的連線)
  • merge 類似於 SQL 型別的連線( join)☆
  • Append ---- 類似於 SQL 中 union
    1.concat (預設上下連線,axis=1時左右連線)
df=pd.DataFrame(np.random.randn(10,4))
df
11098258-7870d175bf573b40.png
pieces=[df[:1],df[6:7]]
pd.concat(pieces)

11098258-b7befe2e10f289e0.png

2.merge 類似於 SQL 型別的連線( join)
根據連線
merge與concat的區別在於,merge需要依據某一共同的行或列來進行合併

left=pd.DataFrame({'key':['foo','foo1'],
                  'lval':[1,2]})
left
11098258-b158d4f97eb6b368.png
right=pd.DataFrame({'key':['foo','foo2'],
                  'rval':[4,5]})
right
11098258-e210038b9e217fdb.png
pd.merge(left,right,on='key')
11098258-2fa427f27a2092d4.png

左連線left,右連線right,外連線outer 預設是inner

pd.merge(left,right,on='key',how='left')
11098258-f39dbcbde4e8acf6.png

3.Append 將一行連線到一個 DataFrame 上
專門用於上下按照同列名連線---- 類似於 SQL 中 union
append是concat的簡略形式,只不過只能在axis=0上進行合併

df=pd.DataFrame(np.random.randn(5,4),columns=list('ABCD'))
df
11098258-7826a8f8234df01b.png
s=df.iloc[1,:]
df.append(s,ignore_index=True)
11098258-8cf68fcc854007ea.png

七、分組和分段

  • 分組(對資料進行分組彙總統計,類似資料透視表)
  • 通過多個列進行分組形成一個層次索引
  • 分段(對資料進行分段或者分箱切割,可用於連續變數的特徵處理,例如woe)
df=pd.DataFrame({'A':['foo','bar','foo','bar','foo','bar','foo','bar'],
                'B':['one','two','three','four','two','two','one','three'],
                'C':np.random.randn(8),
                'D':np.random.randn(8)})
df
11098258-f659b846f9d3e4f7.png

1.分組,並對每個分組執行 sum/count/mean/median(中位數)等函式

df.groupby('A').sum()
df.groupby('A').agg(np.sum)
df.groupby('A').agg({'C':sum,'D':sum})
11098258-2c3fe1b3fac4b41b.png

分組求平均值、最大值、最小值

df.groupby('A').C.agg(['mean','max','min'])

按A中類的個數對C求平均值

df.groupby('A').agg({'C':sum})['C'].mean()

2.通過多個列進行分組形成一個層次索引

df.groupby(['A','B']).sum()
11098258-888afa1e4a18e1a0.png

3.分段(分箱)
有兩種:pd.qcut與pd.cut
按變數取值範圍進行均勻分割cut

cut11=pd.cut(df1["可用額度比值"],4)
cut11.head()
11098258-581ed261e1961924.png

按變數個數進行均勻分割qcut

cut11=pd.qcut(df1["可用額度比值"],4)
cut11
11098258-f0ae51de39d5fcd6.png
cut11=pd.qcut(df1["可用額度比值"],4,labels=False)
cut11.head()
11098258-f2ee9f6cd65d1a78.png

八、軸轉換和資料透視表

  • Stack堆疊
  • 資料透視表
    1.Stack堆疊
tuples=list(zip(*[['bar','bar','baz','baz','foo','foo','qux','qux'],['one','two','one','two','one','two','one','two']]))
index=pd.MultiIndex.from_tuples(tuples,names=['first','ssecond'])
df=pd.DataFrame(np.random.randn(8,2),index=index,columns=['A','B'])
df
11098258-966f9e3422d82cb1.png
stacked=df.stack()
stacked
11098258-46bbc3ac1ea1b09c.png
stacked2=stacked.unstack()
stacked2
11098258-0f0439af340b1dab.png
stacked3=stacked2=stacked.unstack(0)
stacked3
11098258-9df67b7c7d49bd83.png
stacked4=stacked2=stacked.unstack(1)
stacked4

11098258-79f74b8ce1850990.png

2.資料透視表
pd.pivot_table()

df=pd.DataFrame({'A':['one','one','two','three']*3,
                'B':['A','B','C']*4,
                'C':['foo','foo','foo','bar','bar','bar']*2,
                'D':np.random.randn(12),
                'E':np.random.randn(12)})
df
11098258-e1e4dca24c42c677.png
pd.pivot_table(df,values='D',index=['A','B'],columns='C')
11098258-19d90e08d411636c.png
df.pivot_table(df,index=['A','B'],columns=['C'],aggfunc=np.sum)
11098258-ae7f516d73ed12fc.png

九、時間序列

  • 針對時間頻率重取樣
  • 時間型別轉換
  • 時間取樣分組
  • 時間篩選問題
    1.針對時間頻率重取樣
    首先建立一個取樣後的時間序列:
rng=pd.date_range('20120101',periods=61,freq='S')
rng

11098258-550959ea4e7a8a0a.png

序列或者索引為時間時,可以使用.resample()重置取樣頻率

ts=pd.Series(np.random.randint(0,500,len(rng)),index=rng)
ts.resample('1Min',how=sum)
11098258-fd61ebaa013fbdc6.png

另外取樣頻率還有:
W weekly frequency
M 每月最後一天
BM 每個月最後一個工作日
2.將int64型資料轉化成datetime資料

crime.info()
crime.head()
11098258-7fa3b3792cc700a6.png
11098258-7f2edb6e3b3e40e8.png
crime.Year = pd.to_datetime(crime.Year, format='%Y')
crime.info()
crime.head()
11098258-28bf0121e33dcb56.png

11098258-34379a72b249ddf6.png

3.按時間取樣結果分組
例如我們獲得一組資料索引是每一年


11098258-01de68dd7db816cc.png

按如果想按十年進行分組檢視資料情況,即進行時間分組求和,可以使用重取樣
crimes = crime.resample('10AS').sum()

另外,人口不能按十年的直接相加,使用10年內的最大值彙總,在上述基礎上更新population列

population = crime['Population'].resample('10AS').max()
crimes['Population'] = population
11098258-0d0a5bbdb74b7164.png

4.時間篩選問題
通過建立時間分列欄位,進行取樣統計計算,此方法優點是配合query可以實現靈活取樣
例如,如下,計算每一列一月份的平均值


11098258-5296a8030195e6af.png

可以先將時間欄位分列,相當於建立了輔助列

data['date'] = data.index
data['month'] = data['date'].apply(lambda date: date.month)
data['year'] = data['date'].apply(lambda date: date.year)
data['day'] = data['date'].apply(lambda date: date.day)
data.head()
11098258-23edb14050d8a1ca.png

再篩選計算

january_winds = data.query('month == 1')
january_winds.loc[:,'RPT':"MAL"].mean()
11098258-6cb8c9b0bc09bb04.png

按年進行取樣

data.query('month == 1 and day == 1')
11098258-f2403adeec4c1a11.png

按月取樣

data.query('day == 1')
11098258-a71abd2904349a5a.png

時間差,兩個日期之間可以相減,並求對應月數和天數

(data.max() - data.min()).days

十、匯入和儲存資料

  • CSV
  • Excel
    1.匯出
df.to_csv('foo.csv')
df.to_excel('foo.xlsx')
df.to_sql(table_name,connection_object) # 將資料框 (DataFrame)中的資料匯入SQL資料表/資料庫中
df.to_json(filename) # 將資料框 (DataFrame)中的資料匯入JSON格式的檔案中

2.匯入:

pd.read_csv('foo.csv')
pd.read_excel('foo.xlsx')
pd.read_sql(query, connection_object) # 匯入SQL資料表/資料庫中的資料
pd.read_json(json_string) # 匯入JSON格式的字元,URL地址或者檔案中的資料

另外一種常用匯入方式

path3 ='../input/pandas_exercise/exercise_data/drinks.csv'    #'drinks.csv'
drinks = pd.read_csv(path3)

3.檔案匯入引數
在讀取檔案時考慮到格式問題,會使用一些引數進行調整。
參考:https://www.cnblogs.com/datablog/p/6127000.html

sep指定分隔符。如果不指定引數,則會嘗試使用逗號分隔。
其中,會用到正規表示式,可以參考:https://baike.baidu.com/item/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/1700215?fr=aladdin
\s ->匹配任何空白字元,包括空格、製表符、換頁符等
\f -> 匹配一個換頁
\n -> 匹配一個換行符
\r -> 匹配一個回車符
\t -> 匹配一個製表符
\v -> 匹配一個垂直製表符
+->匹配前面的子表示式一次或多次(大於等於1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。
“\s+”則表示匹配任意多個上面的字元。

data = pd.read_table(path6,sep = '\s+') 
data.head()

11098258-26cb05531d08d78c.png

parse_dates 可以將指定的列轉化為時間

data = pd.read_table(path6, sep = "\s+", parse_dates = [[0,1,2]]) 
data.head()
11098258-41e1a3bb7e53d168.png

相關文章