【Python實戰】Pandas:讓你像寫SQL一樣做資料分析(一)
1. 引言
Pandas是一個開源的Python資料分析庫。Pandas把結構化資料分為了三類:
- Series,1維序列,可視作為沒有column名的、只有一個column的DataFrame;
- DataFrame,同Spark SQL中的DataFrame一樣,其概念來自於R語言,為多column並schema化的2維結構化資料,可視作為Series的容器(container);
- Panel,為3維的結構化資料,可視作為DataFrame的容器;
DataFrame較為常見,因此本文主要討論內容將為DataFrame。DataFrame的生成可通過讀取純文字、Json等資料來生成,亦可以通過Python物件來生成:
import pandas as pd
import numpy as np
df = pd.DataFrame({'total_bill': [16.99, 10.34, 23.68, 23.68, 24.59],
'tip': [1.01, 1.66, 3.50, 3.31, 3.61],
'sex': ['Female', 'Male', 'Male', 'Male', 'Female']})
對於DataFrame,我們可以看到其固有屬性:
# data type of columns df.dtypes # indexes df.index # return pandas.Index df.columns # each row, return array[array] df.values # a tuple representing the dimensionality of df df.shape
- .index,為行索引
- .columns,為列名稱(label)
- .dtype,為列資料型別
2. SQL操作
官方Doc給出了部分SQL的Pandas實現,在此基礎上本文給出了一些擴充說明。以下內容基於Python 2.7 + Pandas 0.18.1的版本。
select
SQL中的select是根據列的名稱來選取;Pandas則更為靈活,不但可根據列名稱選取,還可以根據列所在的position選取。相關函式如下:
- loc,基於列label,可選取特定行(根據行index);
- iloc,基於行/列的position;
df.loc[1:3, ['total_bill', 'tip']] df.loc[1:3, 'tip': 'total_bill'] df.iloc[1:3, [1, 2]] df.iloc[1:3, 1: 3]
- at,根據指定行index及列label,快速定位DataFrame的元素;
- iat,與at類似,不同的是根據position來定位的;
df.at[3, 'tip']
df.iat[3, 1]
- ix,為loc與iloc的混合體,既支援label也支援position;
df.ix[1:3, [1, 2]]
df.ix[1:3, ['total_bill', 'tip']]
此外,有更為簡潔的行/列選取方式:
df[1: 3]
df[['total_bill', 'tip']]
# df[1:2, ['total_bill', 'tip']] # TypeError: unhashable type
where
Pandas實現where filter,較為常用的辦法為df[df[colunm] boolean expr]
,比如:
df[df['sex'] == 'Female']
df[df['total_bill'] > 20]
# or
df.query('total_bill > 20')
在where子句中常常會搭配and, or, in, not關鍵詞,Pandas中也有對應的實現:
# and
df[(df['sex'] == 'Female') & (df['total_bill'] > 20)]
# or
df[(df['sex'] == 'Female') | (df['total_bill'] > 20)]
# in
df[df['total_bill'].isin([21.01, 23.68, 24.59])]
# not
df[-(df['sex'] == 'Male')]
df[-df['total_bill'].isin([21.01, 23.68, 24.59])]
# string function
df = df[(-df['app'].isin(sys_app)) & (-df.app.str.contains('^微信\d+$'))]
對where條件篩選後只有一行的dataframe取其中某一列的值,其兩種實現方式如下:
total = df.loc[df['tip'] == 1.66, 'total_bill'].values[0]
total = df.get_value(df.loc[df['tip'] == 1.66].index.values[0], 'total_bill')
distinct
df.drop_duplicates(subset=['sex'], keep='first', inplace=True)
包含引數:
- subset,為選定的列做distinct,預設為所有列;
- keep,值選項{'first', 'last', False},保留重複元素中的第一個、最後一個,或全部刪除;
- inplace ,預設為False,返回一個新的dataframe;若為True,則返回去重後的原dataframe
group
group一般會配合合計函式(Aggregate functions)使用,比如:count、avg等。Pandas對合計函式的支援有限,有count和size函式實現SQL的count:
df.groupby('sex').size()
df.groupby('sex').count()
df.groupby('sex')['tip'].count()
對於多合計函式,
select sex, max(tip), sum(total_bill) as total
from tips_tb
group by sex;
實現在agg()中指定dict:
df.groupby('sex').agg({'tip': np.max, 'total_bill': np.sum})
# count(distinct **)
df.groupby('tip').agg({'sex': pd.Series.nunique})
as
SQL中使用as修改列的別名,Pandas也支援這種修改:
# first implementation
df.columns = ['total', 'pit', 'xes']
# second implementation
df.rename(columns={'total_bill': 'total', 'tip': 'pit', 'sex': 'xes'}, inplace=True)
其中,第一種方法的修改是有問題的,因為其是按照列position逐一替換的。因此,我推薦第二種方法。
join
Pandas中join的實現也有兩種:
# 1.
df.join(df2, how='left'...)
# 2.
pd.merge(df1, df2, how='left', left_on='app', right_on='app')
第一種方法是按DataFrame的index進行join的,而第二種方法才是按on指定的列做join。Pandas滿足left、right、inner、full outer四種join方式。
order
Pandas中支援多列order,並可以調整不同列的升序/降序,有更高的排序自由度:
df.sort_values(['total_bill', 'tip'], ascending=[False, True])
top
對於全域性的top:
df.nlargest(3, columns=['total_bill'])
對於分組top,MySQL的實現(採用自join的方式):
select a.sex, a.tip
from tips_tb a
where (
select count(*)
from tips_tb b
where b.sex = a.sex and b.tip > a.tip
) < 2
order by a.sex, a.tip desc;
Pandas的等價實現,思路與上類似:
# 1.
df.assign(rn=df.sort_values(['total_bill'], ascending=False)
.groupby('sex')
.cumcount()+1)\
.query('rn < 3')\
.sort_values(['sex', 'rn'])
# 2.
df.assign(rn=df.groupby('sex')['total_bill']
.rank(method='first', ascending=False)) \
.query('rn < 3') \
.sort_values(['sex', 'rn'])
replace
replace函式提供對dataframe全域性修改,亦可通過where條件進行過濾修改(搭配loc):
# overall replace
df.replace(to_replace='Female', value='Sansa', inplace=True)
# dict replace
df.replace({'sex': {'Female': 'Sansa', 'Male': 'Leone'}}, inplace=True)
# replace on where condition
df.loc[df.sex == 'Male', 'sex'] = 'Leone'
自定義
除了上述SQL操作外,Pandas提供對每列/每一元素做自定義操作,為此而設計以下三個函式:
- map(func),為Series的函式,DataFrame不能直接呼叫,需取列後再呼叫;
- apply(func),對DataFrame中的某一行/列進行func操作;
- applymap(func),為element-wise函式,對每一個元素做func操作
df['tip'].map(lambda x: x - 1)
df[['total_bill', 'tip']].apply(sum)
df.applymap(lambda x: x.upper() if type(x) is str else x)
3. 實戰
環比增長
現有兩個月APP的UV資料,要得到月UV環比增長;該操作等價於兩個Dataframe left join後按指定列做減操作:
def chain(current, last):
df1 = pd.read_csv(current, names=['app', 'tag', 'uv'], sep='\t')
df2 = pd.read_csv(last, names=['app', 'tag', 'uv'], sep='\t')
df3 = pd.merge(df1, df2, how='left', on='app')
df3['uv_y'] = df3['uv_y'].map(lambda x: 0.0 if pd.isnull(x) else x)
df3['growth'] = df3['uv_x'] - df3['uv_y']
return df3[['app', 'growth', 'uv_x', 'uv_y']].sort_values(by='growth', ascending=False)
差集
對於給定的列,一個Dataframe過濾另一個Dataframe該列的值;相當於集合的差集操作:
def difference(left, right, on):
"""
difference of two dataframes
:param left: left dataframe
:param right: right dataframe
:param on: join key
:return: difference dataframe
"""
df = pd.merge(left, right, how='left', on=on)
left_columns = left.columns
col_y = df.columns[left_columns.size]
df = df[df[col_y].isnull()]
df = df.ix[:, 0:left_columns.size]
df.columns = left_columns
return df
相關推薦
【Python實戰】Pandas:讓你像寫SQL一樣做資料分析(一)
1. 引言 Pandas是一個開源的Python資料分析庫。Pandas把結構化資料分為了三類: Series,1維序列,可視作為沒有column名的、只有一個column的DataFrame; DataFrame,同Spark SQL中的DataFrame一樣,其概念來自於R語言,為多column並sch
【Python實戰】Pandas:讓你像寫SQL一樣做資料分析(二)
1. 引言 前一篇介紹了Pandas實現簡單的SQL操作,本篇中將主要介紹一些相對複雜一點的操作。為了方便後面實操,先給出一份簡化版的裝置統計資料: 0 android NLL 387546520 2099457911 0 ios NLL 52877990 916421755 1 and
用實戰玩轉pandas資料分析(一)——使用者消費行為分析(python)
CD商品訂單資料的分析總結。根據訂單資料(使用者的消費記錄),從時間維度和使用者維度,分析該網站使用者的消費行為。通過此案例,總結訂單資料的一些共性,能通過使用者的消費記錄挖掘出對業務有用的資訊。對其他產品的線上消費資料分析有一定的借鑑價值,能達到舉一反三的效果。 訂單交易資料分析 [
寫Markdown費事?Typora讓你像寫word一樣行雲流水,所見即所得。
Typora 簡介 Typora刪除了預覽視窗,以及所有其他不必要的干擾。取而代之的是實時預覽。 Markdown的語法因不同的解析器或編輯器而異,Typora使用的是GitHub Flavored Markdown。 下載 Typora下載。 常用快捷鍵 加粗: 
利用python/pandas/numpy做資料分析(三)-透視表pivot_table
透視表,根據一個或多個鍵進行聚合,並根據行列上的分組鍵將資料分配到各個矩形區域中. import numpy as np data=pd.DataFrame(np.arange(6).reshape((2,3)), index
【ML專案】基於網路爬蟲和資料探勘演算法的web招聘資料分析(一)——資料獲取與處理
前言 這個專案是在學校做的,主要是想對各大招聘網站的招聘資料進行分析,沒準能從中發現什麼,這個專案週期有些長,以至於在專案快要結束時發現網上已經有了一些相關的專案,我後續會把相關的專案材料放在我的GitHub上面,連結為:https://github.com/
bigdata資料分析(一):Java環境配置
Java環境 1.下載jdk(用FileZilla工具連線伺服器後上傳到需要安裝的目錄) 在 /opt/deploy 下新建 java 資料夾: # mkdir / opt/deploy /java 解壓命令:tar zxvf 壓縮包名稱 (例如:tar zxvf jdk-8u191-
利用python做資料分析(六)-reindex
DataFrame.reindex(index=None, columns=None, **kwargs) reindex 函式的引數 引數 說明 method 插值填充方法 fill_value 引入的缺失資料值
用Python做股市資料分析(一)
AAPL GOOG MSFT Date 2016-01-04 1.000000 1.000000 1.000000 2016-01-05 0.974941 1.000998 1.004562 2016-01-06 0.955861 1.002399 0.986314 201
【MongoDb入門】15分鐘讓你敢說自己會用MongoDB了
一.MongDB是什麼呢,我該如何下手呢? MongoDB是一個基於分散式檔案儲存的資料庫。由C++語言編寫。旨在為WEB應用提供可擴充套件的高效能資料儲存解決方案。 如果小夥伴你的機器上還沒有安裝MongoDb的話請快快去安裝吧,下載地址:https://www.mongodb.com/download
【Python實戰】用Scrapyd把Scrapy爬蟲一步一步部署到騰訊雲
將我們的爬蟲部署到騰訊雲伺服器上面。廢話不多說,我們就來實戰操作吧。 這裡選擇什麼雲服務都是可以的,阿里雲,AWS,騰訊雲,其他雲都是沒有問題的。部署方法基本一樣,這裡為了方便,所以筆者選擇了騰訊雲來做講解。 既然我們選擇了騰訊雲,首先去騰訊雲的官網,註冊登入一下。 點選複製https:
7個Python實戰專案程式碼,讓你分分鐘晉級大神!
關於Python有一句名言:不要重複造輪子。 但是問題有三個: 1、你不知道已經有哪些輪子已經造好了,哪個適合你用。有名有姓的的著名輪子就400多個,更別說沒名沒姓自己在製造中的輪子。 2、確實沒重複造輪子,但是在重複製造汽車。包括好多大神寫的好幾百行程式碼,為的是
【保險專題】一則故事讓你輕鬆瞭解保險的實質
正文: 100個學徒工來到一家五星級大酒店學習廚藝,他們要勤勤懇懇學習十年才能出師。學徒們的薪水不高,一年只有幾百塊,但是五星級酒店的餐具都非常名貴,一個盤子要1000塊錢。如果哪個學徒不小心打壞了一個盤子,那麼他不僅要傾家蕩產來賠償這1000元錢,還可
【Python實戰】機型自動化標註(搜狗爬蟲實現)
1. 引言 從安卓手機收集上來的機型大都為這樣: mi|5 mi|4c mi 4c 2014022 kiw-al10 nem-tl00h 收集的機型大都雜亂無章,不便於做統計分析。因此,標註顯得尤為重要。 中關村線上有對國內大部分手機的介紹情況,包括手機機型nem-tl00h及其對應的常見名稱榮耀暢玩5C
【Python實戰】Scrapy豌豆莢應用市場爬蟲
對於給定的大量APP,如何爬取與之對應的(應用市場)分類、描述的資訊?且看下面分解。 1. 頁面分析 當我們在豌豆莢首頁搜尋框輸入微信後,會跳轉到搜尋結果的頁面,其url為http://www.wandoujia.com/search?key=%微信。搜尋結果一般是按相關性排序的;所以,我們認為第一條搜尋結果
【Python實戰】Django建站筆記
前一段時間,用Django搭建一個報表分析的網站;藉此正好整理一下筆記。 1. 安裝 python有包管理工具pip,直接cd Python27/Scripts,輸入 pip install django # install by version pip install --upgrade Django==
7個Python實戰專案程式碼,讓你感受下大神是如何起飛的!
關於Python有一句名言:不要重複造輪子。 但是問題有三個: 1、你不知道已經有哪些輪子已經造好了,哪個適合你用。有名有姓的的著名輪子就400多個,更別說沒名沒姓自己在製造中的輪子。 2、確實沒重複造輪子,但是在重複製造汽車。包括好多大神寫的好幾百行程式碼,為的是解決
【python】python資料結構(一)——線性表:順序表的實現
前言 這一系列文章將介紹基於python語言的資料結構,主要涉及線性表、字串、棧和佇列、二叉樹和樹、圖、字典和集合、排序等。 線性表及分類 線性表是一類元素序列的抽象,是某類元素的集合,記錄著元素之間的順序關係。python中的list和tuple都支援線性表的需要,只是t
【Unity Shaders】使用CgInclude讓你的Shader模組化——建立CgInclude檔案儲存光照模型
這裡是本書所有的插圖。這裡是本書所需的程式碼和資源(當然你也可以從官網下載)。========================================== 分割線 ==========================================寫在前面瞭解內建的C
【Unity Shaders】使用CgInclude讓你的Shader模組化——Unity內建的CgInclude檔案
這裡是本書所有的插圖。這裡是本書所需的程式碼和資源(當然你也可以從官網下載)。========================================== 分割線 ==========================================寫在前面啦啦啦,又開