Python大數據處理模塊Pandas


 

Python大數據處理模塊Pandas

 

Pandas使用一個二維的數據結構DataFrame來表示表格式的數據,相比較於Numpy,Pandas可以存儲混合的數據結構,同時使用NaN來表示缺失的數據,而不用像Numpy一樣要手工處理缺失的數據,並且Pandas使用軸標簽來表示行和列

 

1、文件讀取
首先將用到的pandas和numpy加載進來
import pandas as pd
import numpy as np
讀取數據:
#csv和xlsx分別用read_csv和read_xlsx,下面以csv為例

df=pd.read_csv('f:\1024.csv') 


2、查看數據

df.head()  

#默認出5行,​括號里可以填其他數據

3、查看數據類型

df.dtypes

4、利用現有數據生成一列新數據

比如:max_time和min_time是現有的兩列,現在業務需要生成一列gs,gs=max_time-min_time

df.['gs']=df.['max_time']-['min_time']

#查看是否成功

df.head()

5、查看基本統計量

df.describe(include='all')                 # all代表需要將所有列都列出

 

 

通常來說,數據是CSV格式,就算不是,至少也可以轉換成CSV格式。在Python中,我們的操作如下:

 

import pandas as pd

 

# Reading data locally

df = pd.read_csv('/Users/al-ahmadgaidasaad/Documents/d.csv')

 

# Reading data from web

data_url = "https://raw.githubusercontent.com/alstat/Analysis-with-Programming/master/2014/Python/Numerical-Descriptions-of-the-Data/data.csv"

 

df = pd.read_csv(data_url)

 

為了讀取本地CSV文件,我們需要pandas這個數據分析庫中的相應模塊。

 

其中的read_csv函數能夠讀取本地和web數據

 

 

 

# Head of the data

print df.head()

 

# OUTPUT

    Abra  Apayao  Benguet  Ifugao  Kalinga

0   1243    2934      148    3300    10553

1   4158    9235     4287    8063    35257

2   1787    1922     1955    1074     4544

3  17152   14501     3536   19607    31687

4   1266    2385     2530    3315     8520

 

# Tail of the data

 

print df.tail()

 

# OUTPUT

     Abra  Apayao  Benguet  Ifugao  Kalinga

74   2505   20878     3519   19737    16513

75  60303   40065     7062   19422    61808

76   6311    6756     3561   15910    23349

77  13345   38902     2583   11096    68663

78   2623   18264     3745   16787    16900

 

上述操作等價於通過print(head(df))來打印數據的前6行,以及通過print(tail(df))來打印數據的后6行。

 

 

當然Python中,默認打印是5行,而R則是6行。因此R的代碼head(df, n = 10),

 

在Python中就是df.head(n = 10),打印數據尾部也是同樣道理。

 

 

在Python中,我們則使用columns和index屬性來提取,如下:

 

 

# Extracting column names

 

print df.columns

 

# OUTPUT

 

Index([u'Abra', u'Apayao', u'Benguet', u'Ifugao', u'Kalinga'], dtype='object')

 

# Extracting row names or the index

 

print df.index

 

# OUTPUT

Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], dtype='int64')

 

數據轉置使用T方法,

 

 

# Transpose data

print df.T

 

# OUTPUT

            0      1     2      3     4      5     6      7     8      9  

Abra      1243   4158  1787  17152  1266   5576   927  21540  1039   5424  

Apayao    2934   9235  1922  14501  2385   7452  1099  17038  1382  10588  

Benguet    148   4287  1955   3536  2530    771  2796   2463  2592   1064  

Ifugao    3300   8063  1074  19607  3315  13134  5134  14226  6842  13828  

Kalinga  10553  35257  4544  31687  8520  28252  3106  36238  4973  40140  

 

         ...       69     70     71     72     73     74     75     76     77  

Abra     ...    12763   2470  59094   6209  13316   2505  60303   6311  13345  

Apayao   ...    37625  19532  35126   6335  38613  20878  40065   6756  38902  

Benguet  ...     2354   4045   5987   3530   2585   3519   7062   3561   2583  

Ifugao   ...     9838  17125  18940  15560   7746  19737  19422  15910  11096  

Kalinga  ...    65782  15279  52437  24385  66148  16513  61808  23349  68663  

 

            78  

Abra      2623  

Apayao   18264  

Benguet   3745  

Ifugao   16787  

Kalinga  16900  

 

其他變換,例如排序就是用sort屬性。現在我們提取特定的某列數據。

Python中,可以使用iloc或者ix屬性。但是我更喜歡用ix,因為它更穩定一些。假設我們需數據第一列的前5行,我們有:

 

print df.ix[:, 0].head()

 

# OUTPUT

0     1243

1     4158

2     1787

3    17152

4     1266

Name: Abra, dtype: int64

 

 

順便提一下,Python的索引是從0開始而非1。為了取出從11到20行的前3列數據,我們有:

 

print df.ix[10:20, 0:3]

 

# OUTPUT

    Abra  Apayao  Benguet

10    981    1311     2560

11  27366   15093     3039

12   1100    1701     2382

13   7212   11001     1088

14   1048    1427     2847

15  25679   15661     2942

16   1055    2191     2119

17   5437    6461      734

18   1029    1183     2302

19  23710   12222     2598

20   1091    2343     2654

 

 

上述命令相當於df.ix[10:20, ['Abra', 'Apayao', 'Benguet']]。

 

為了舍棄數據中的列,這里是列1(Apayao)和列2(Benguet),我們使用drop屬性,如下:

 

print df.drop(df.columns[[1, 2]], axis = 1).head()

 

# OUTPUT

    Abra  Ifugao  Kalinga

0   1243    3300    10553

1   4158    8063    35257

2   1787    1074     4544

3  17152   19607    31687

4   1266    3315     8520

 

axis 參數告訴函數到底舍棄列還是行。如果axis等於0,那么就舍棄行。

 

統計描述

 

下一步就是通過describe屬性,對數據的統計特性進行描述:

 

print df.describe()

 

# OUTPUT

               Abra        Apayao      Benguet        Ifugao       Kalinga

count     79.000000     79.000000    79.000000     79.000000     79.000000

mean   12874.379747  16860.645570  3237.392405  12414.620253  30446.417722

std    16746.466945  15448.153794  1588.536429   5034.282019  22245.707692

min      927.000000    401.000000   148.000000   1074.000000   2346.000000

25%     1524.000000   3435.500000  2328.000000   8205.000000   8601.500000

50%     5790.000000  10588.000000  3202.000000  13044.000000  24494.000000

75%    13330.500000  33289.000000  3918.500000  16099.500000  52510.500000

max    60303.000000  54625.000000  8813.000000  21031.000000  68663.000000

 

Python有一個很好的統計推斷包。那就是scipy里面的stats。ttest_1samp實現了單樣本t檢驗。因此,如果我們想檢驗數據Abra列的稻谷產量均值,通過零假設,這里我們假定總體稻谷產量均值為15000,我們有:

 

 from scipy import stats as ss

 

# Perform one sample t-test using 1500 as the true mean

print ss.ttest_1samp(a = df.ix[:, 'Abra'], popmean = 15000)

 

# OUTPUT

(-1.1281738488299586, 0.26270472069109496)

 

返回下述值組成的元祖:

 

t : 浮點或數組類型

t統計量

prob : 浮點或數組類型

two-tailed p-value 雙側概率值

通過上面的輸出,看到p值是0.267遠大於α等於0.05,因此沒有充分的證據說平均稻谷產量不是150000。將這個檢驗應用到所有的變量,同樣假設均值為15000,我們有:

 

print ss.ttest_1samp(a = df, popmean = 15000)

 

# OUTPUT

(array([ -1.12817385,   1.07053437, -65.81425599,  -4.564575  ,   6.17156198]),

array([  2.62704721e-01,   2.87680340e-01,   4.15643528e-70,

          1.83764399e-05,   2.82461897e-08]))

 

 

第一個數組是t統計量,第二個數組則是相應的p值。

 

可視化

 

Python中有許多可視化模塊,最流行的當屬matpalotlib庫。稍加提及,我們也可選擇bokeh和seaborn模塊。之前的博文中,我已經說明了matplotlib庫中的盒須圖模塊功能。

 

# Import the module for plotting

import matplotlib.pyplot as plt

plt.show(df.plot(kind = 'box'))

 

 

現在,我們可以用pandas模塊中集成R的ggplot主題來美化圖表。要使用ggplot,我們只需要在上述代碼中多加一行,

 

 

import matplotlib.pyplot as plt

pd.options.display.mpl_style = 'default' # Sets the plotting display theme to ggplot2

df.plot(kind = 'box')

 

 

# Import the seaborn library

import seaborn as sns

# Do the boxplot

plt.show(sns.boxplot(df, widths = 0.5, color = "pastel"))

 

 

import numpy as np

import scipy.stats as ss

 

def case(n = 10, mu = 3, sigma = np.sqrt(5), p = 0.025, rep = 100):

    m = np.zeros((rep, 4))

 

    for i in range(rep):

        norm = np.random.normal(loc = mu, scale = sigma, size = n)

        xbar = np.mean(norm)

        low = xbar - ss.norm.ppf(q = 1 - p) * (sigma / np.sqrt(n))

        up = xbar + ss.norm.ppf(q = 1 - p) * (sigma / np.sqrt(n))

 

        if (mu > low) & (mu < up):

            rem = 1

        else:

            rem = 0

 

        m[i, :] = [xbar, low, up, rem]

 

    inside = np.sum(m[:, 3])

    per = inside / rep

    desc = "There are " + str(inside) + " confidence intervals that contain "

           "the true mean (" + str(mu) + "), that is " + str(per) + " percent of the total CIs"

 

    return {"Matrix": m, "Decision": desc}

 

 

import numpy as np

import scipy.stats as ss

 

def case2(n = 10, mu = 3, sigma = np.sqrt(5), p = 0.025, rep = 100):

    scaled_crit = ss.norm.ppf(q = 1 - p) * (sigma / np.sqrt(n))

    norm = np.random.normal(loc = mu, scale = sigma, size = (rep, n))

 

    xbar = norm.mean(1)

    low = xbar - scaled_crit

    up = xbar + scaled_crit

 

    rem = (mu > low) & (mu < up)

    m = np.c_[xbar, low, up, rem]

 

    inside = np.sum(m[:, 3])

    per = inside / rep

    desc = "There are " + str(inside) + " confidence intervals that contain "

           "the true mean (" + str(mu) + "), that is " + str(per) + " percent of the total CIs"

    return {"Matrix": m, "Decision": desc}

 


 

讀取數據

Pandas使用函數read_csv()來讀取csv文件

復制代碼

import pandas

food_info = ('food_info.csv')
print(type(food_info))
# 輸出:<class 'pandas.core.frame.DataFrame'> 可見讀取后變成一個DataFrame變量

復制代碼

 

該文件的內容如下:

圖片3

 

使用函數head( m )來讀取前m條數據,如果沒有參數m,默認讀取前五條數據

first_rows = food_info.head()

first_rows = food_info.head(3)

由於DataFrame包含了很多的行和列,

Pandas使用省略號(...)來代替顯示全部的行和列,可以使用colums屬性來顯示全部的列名

復制代碼

print(food_info.columns)

# 輸出:輸出全部的列名,而不是用省略號代替

Index(['NDB_No', 'Shrt_Desc', 'Water_(g)', 'Energ_Kcal', 'Protein_(g)', 'Lipid_Tot_(g)', 'Ash_(g)', 'Carbohydrt_(g)', 'Fiber_TD_(g)', 'Sugar_Tot_(g)', 'Calcium_(mg)', 'Iron_(mg)', 'Magnesium_(mg)', 'Phosphorus_(mg)', 'Potassium_(mg)', 'Sodium_(mg)', 'Zinc_(mg)', 'Copper_(mg)', 'Manganese_(mg)', 'Selenium_(mcg)', 'Vit_C_(mg)', 'Thiamin_(mg)', 'Riboflavin_(mg)', 'Niacin_(mg)', 'Vit_B6_(mg)', 'Vit_B12_(mcg)', 'Vit_A_IU', 'Vit_A_RAE', 'Vit_E_(mg)', 'Vit_D_mcg', 'Vit_D_IU', 'Vit_K_(mcg)', 'FA_Sat_(g)', 'FA_Mono_(g)', 'FA_Poly_(g)', 'Cholestrl_(mg)'], dtype='object')

復制代碼

可以使用tolist()函數轉化為list

food_info.columns.tolist()

與Numpy一樣,用shape屬性來顯示數據的格式

 

dimensions = food_info.shapeprint(dimensions)
print(dimensions)
​
輸出:(8618,36) ,

其中dimensions[0]為8618,dimensions[1]為36

 

與Numpy一樣,用dtype屬性來顯示數據類型,Pandas主要有以下幾種dtype:

  • object -- 代表了字符串類型

  • int -- 代表了整型

  • float -- 代表了浮點數類型

  • datetime -- 代表了時間類型

  • bool -- 代表了布爾類型

 

當讀取了一個文件之后,Pandas會通過分析值來推測每一列的數據類型

復制代碼

print()

輸出:每一列對應的數據類型

NDB_No            int64

Shrt_Desc           object

Water_(g)           float64

Energ_Kcal          int64

Protein_(g)          float64

...

 

索引

讀取了文件后,Pandas會把文件的一行作為列的索引標簽,使用行數字作為行的索引標簽

圖片4

注意,行標簽是從數字0開始的

Pandas使用Series數據結構來表示一行或一列的數據,類似於Numpy使用向量來表示數據。Numpy只能使用數字來索引,而Series可以使用非數字來索引數據,當你選擇返回一行數據的時候,Series並不僅僅返回該行的數據,同時還有每一列的標簽的名字。

譬如要返回文件的第一行數據,Numpy就會返回一個列表(但你可能不知道每一個數字究竟代表了什么)

圖片5

而Pandas則會同時把每一列的標簽名返回(此時就很清楚數據的意思了)

圖片6

 

選擇數據

Pandas使用loc[]方法來選擇行的數據

復制代碼

# 選擇單行數據:

food_info.loc[0]   # 選擇行標號為0的數據,即第一行數據
food_info.loc[6]   # 選擇行標號為6的數據,即第七行數據

# 選擇多行數據:

food_info.loc[3:6] # 使用了切片,注意:由於這里使用loc[]函數,所以返回的是行標號為3,4,5,6的數據,與python的切片不同的是這里會返回最后的標號代表的數據,但也可以使用python的切片方法:food_info[3:7]

food_info.loc[[2,5,10]] # 返回行標號為2,5,10三行數據

練習:返回文件的最后五行

方法一:

length = food_info.shape[0]

last_rows = food_info.loc[length-5:length-1]

方法二:

num_rows = food_info.shape[0]

last_rows = food_info[num_rows-5:num_rows]

Pandas直接把列名稱填充就能返回該列的數據

ndb_col = food_info["NDB_No"] # 返回列名稱為NDB_No的那一列的數據

zinc_copper = food_info[["Zinc_(mg)", "Copper_(mg)"]] # 返回兩列數據

復制代碼

 

簡單運算

現在要按照如下公式計算所有食物的健康程度,並按照降序的方式排列結果:

Score=2×(Protein_(g))−0.75×(Lipid_Tot_(g))

對DataFrame中的某一列數據進行算術運算,其實是對該列中的所有元素進行逐一的運算,譬如:

water_energy = food_info["Water_(g)"] * food_info["Energ_Kcal"]

原理:

圖片7

由於每一列的數據跨度太大,有的數據是從0到100000,而有的數據是從0到10,所以為了盡量減少數據尺度對運算結果的影響,采取最簡單的方法來規范化數據,那就是將每個數值都除以該列的最大值,從而使所有數據都處於0和1之間。其中max()函數用來獲取該列的最大值.

復制代碼

food_info['Normalized_Protein'] = food_info['Protein_(g)'] / food_info['Protein_(g)'].max()

food_info['Normalized_Fat'] = food_info['Lipid_Tot_(g)'] / food_info['Lipid_Tot_(g)'].max()

food_info['Norm_Nutr_Index'] = food_info["Normalized_Protein"] * 2 - food_info["Normalized_Fat"] * 0.75

注意:上面的兩個語句已經在原來的DataFrame中添加了三列,列名分別為Normalized_Protein和Normalized_Fat,Norm_Nutr_Index。只需要使用中括號和賦值符就能添加新列,類似於字典

對DataFrame的某一列數據排序,只需要使用函數sort()即可

food_info.sort("Sodium_(mg)") # 函數參數為列名,默認是按照升序排序,同時返回一個新的

DataFramefood_info.sort("Norm_Nutr_Index", inplace=True, ascending=False ) 

# 通過inplace參數來控制在原表排序,而不是返回一個新的對象;ascending參數用來控制是否升序排序

 

import pandas as pd

read_csv()

讀寫csv數據

df = pd.read_csv(path): 讀入csv文件,形成一個數據框(data.frame)

df = pd.read_csv(path, header=None) 不要把第一行作為header

to_csv()

* 注意,默認會將第一行作為header,並且默認會添加index,所以不需要的話需要手動禁用 *

df.to_csv(path, header=False, index=False)

數據框操作

df.head(1) 讀取頭幾條數據

df.tail(1) 讀取后幾條數據

df[‘date’] 獲取數據框的date列

df.head(1)[‘date’] 獲取第一行的date列

df.head(1)[‘date’][0] 獲取第一行的date列的元素值

sum(df[‘ability’]) 計算整個列的和

df[df[‘date’] == ‘20161111’] 獲取符合這個條件的行

df[df[‘date’] == ‘20161111’].index[0] 獲取符合這個條件的行的行索引的值

df.iloc[1] 獲取第二行

df.iloc[1][‘test2’] 獲取第二行的test2值

10 mins to pandas 
df.index 獲取行的索引

df.index[0] 獲取第一個行索引

df.index[-1] 獲取最后一個行索引,只是獲取索引值

df.columns 獲取列標簽

df[0:2] 獲取第1到第2行,從0開始,不包含末端

df.loc[1] 獲取第二行

df.loc[:,’test1’] 獲取test1的那一列,這個冒號的意思是所有行,逗號表示行與列的區分

df.loc[:,[‘test1’,’test2’]] 獲取test1列和test2列的數據

df.loc[1,[‘test1’,’test2’]] 獲取第二行的test1和test2列的數據

df.at[1,’test1’] 表示取第二行,test1列的數據,和上面的方法類似

df.iloc[0] 獲取第一行

df.iloc[0:2,0:2] 獲取前兩行前兩列的數據

df.iloc[[1,2,4],[0,2]] 獲取第1,2,4行中的0,2列的數據

(df[2] > 1).any() 對於Series應用any()方法來判斷是否有符合條件的

一、            創建對象

可以通過 Data Structure Intro Setion 來查看有關該節內容的詳細信息。

1、可以通過傳遞一個list對象來創建一個Series,pandas會默認創建整型索引:

2、通過傳遞一個numpy array,時間索引以及列標簽來創建一個DataFrame:

3、通過傳遞一個能夠被轉換成類似序列結構的字典對象來創建一個DataFrame:

4、查看不同列的數據類型:

5、如果你使用的是IPython,使用Tab自動補全功能會自動識別所有的屬性以及自定義的列,下圖中是所有能夠被自動識別的屬性的一個子集:

二、            查看數據

詳情請參閱:Basics Section

 

1、  查看frame中頭部和尾部的行:

2、  顯示索引、列和底層的numpy數據:

3、  describe()函數對於數據的快速統計匯總:

4、  對數據的轉置:

5、  按軸進行排序

6、  按值進行排序

三、            選擇

雖然標准的Python/Numpy的選擇和設置表達式都能夠直接派上用場,但是作為工程使用的代碼,我們推薦使用經過優化的pandas數據訪問方式: .at, .iat, .loc, .iloc 和 .ix詳情請參閱Indexing and Selecing Data 和 MultiIndex / Advanced Indexing

l  獲取

1、 選擇一個單獨的列,這將會返回一個Series,等同於df.A:

2、 通過[]進行選擇,這將會對行進行切片

l  通過標簽選擇

1、 使用標簽來獲取一個交叉的區域

2、 通過標簽來在多個軸上進行選擇

3、 標簽切片

4、 對於返回的對象進行維度縮減

5、 獲取一個標量

6、 快速訪問一個標量(與上一個方法等價)

l  通過位置選擇

1、 通過傳遞數值進行位置選擇(選擇的是行)

2、 通過數值進行切片,與numpy/python中的情況類似

3、 通過指定一個位置的列表,與numpy/python中的情況類似

4、 對行進行切片

5、 對列進行切片

6、 獲取特定的值

l  布爾索引

1、 使用一個單獨列的值來選擇數據:

2、 使用where操作來選擇數據:

3、 使用isin()方法來過濾:

 

l  設置

1、 設置一個新的列:

2、 通過標簽設置新的值:

3、 通過位置設置新的值:

4、 通過一個numpy數組設置一組新值:

上述操作結果如下:

5、 通過where操作來設置新的值:

四、            缺失值處理

在pandas中,使用np.nan來代替缺失值,這些值將默認不會包含在計算中,詳情請參閱:Missing Data Section

1、  reindex()方法可以對指定軸上的索引進行改變/增加/刪除操作,這將返回原始數據的一個拷貝:、

2、  去掉包含缺失值的行:

3、  對缺失值進行填充:

4、  對數據進行布爾填充:

五、            相關操作

詳情請參與 Basic Section On Binary Ops

  • 統計(相關操作通常情況下不包括缺失值)

1、  執行描述性統計:

2、  在其他軸上進行相同的操作:

3、  對於擁有不同維度,需要對齊的對象進行操作。Pandas會自動的沿着指定的維度進行廣播:

  • Apply

1、  對數據應用函數:

  • 直方圖

具體請參照:Histogramming and Discretization

 

  • 字符串方法

Series對象在其str屬性中配備了一組字符串處理方法,可以很容易的應用到數組中的每個元素,如下段代碼所示。更多詳情請參考:Vectorized String Methods.

六、            合並

Pandas提供了大量的方法能夠輕松的對Series,DataFrame和Panel對象進行各種符合各種邏輯關系的合並操作。具體請參閱:Merging section

  • Concat

  • Append 將一行連接到一個DataFrame上,具體請參閱Appending

七、            分組

對於”group by”操作,我們通常是指以下一個或多個操作步驟:

  • (Splitting)按照一些規則將數據分為不同的組;

  • (Applying)對於每組數據分別執行一個函數;

  • (Combining)將結果組合到一個數據結構中;

詳情請參閱:Grouping section

1、  分組並對每個分組執行sum函數:

2、  通過多個列進行分組形成一個層次索引,然后執行函數:

八、            Reshaping

詳情請參閱 Hierarchical Indexing 和 Reshaping

  • Stack

可以從這個數據中輕松的生成數據透視表:

九、            時間序列

Pandas在對頻率轉換進行重新采樣時擁有簡單、強大且高效的功能(如將按秒采樣的數據轉換為按5分鍾為單位進行采樣的數據)。這種操作在金融領域非常常見。具體參考:Time Series section

1、  時區表示:

2、  時區轉換:

3、  時間跨度轉換:

4、  時期和時間戳之間的轉換使得可以使用一些方便的算術函數。

十、            Categorical

從0.15版本開始,pandas可以在DataFrame中支持Categorical類型的數據,詳細 介紹參看:categorical introductionAPI documentation

1、  將原始的grade轉換為Categorical數據類型:

2、  將Categorical類型數據重命名為更有意義的名稱:

3、  對類別進行重新排序,增加缺失的類別:

4、  排序是按照Categorical的順序進行的而不是按照字典順序進行:

5、  對Categorical列進行排序時存在空的類別:

十一、           畫圖

具體文檔參看:Plotting docs

對於DataFrame來說,plot是一種將所有列及其標簽進行繪制的簡便方法:

十二、           導入和保存數據

1、  寫入csv文件:

2、  從csv文件中讀取:

1、  寫入HDF5存儲:

2、  從HDF5存儲中讀取:

1、  寫入excel文件:

2、  從excel文件中讀取:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM