python如何从一个dataframe提取相应的行组成一个新的dataframe_Python|专题(1)——数据处理常规操作集(1)...
大家好!好久不見!適逢國慶,先祝我親愛的祖國七十周年生日快樂!
這一系列文章是針對最近在實習(xí)中做的一些數(shù)據(jù)預(yù)處理操作的整理。我們希望通過它們,帶領(lǐng)大家了解和熟悉一些python做數(shù)據(jù)清洗,數(shù)據(jù)整合等的常見操作。
請注意我們這是專題文章,也就是說這一系列文章并不假設(shè)你對python是零基礎(chǔ)的。但是如果你和我一樣,也是一個數(shù)據(jù)科學(xué)中探索的小白,那么我希望你也能夠通過這些文章,在一個一個的數(shù)據(jù)處理的坑中爬起來,總結(jié)經(jīng)驗,奮勇前行~
寫這一系列文章之前我也咨詢了老板的意見,也得到了他的同意。說這句話的意思是:所有這里涉及的操作,在數(shù)據(jù)分析中都是基礎(chǔ),重要和容易踩坑的。所以即使你現(xiàn)在覺得它們難以理解,或者用不上,以后也大概率會碰到。還需要和大家說的是,為了防止泄露商業(yè)機密和業(yè)務(wù)材料,我們的數(shù)據(jù)集事先做過處理。
那么我們開始吧。沒有特殊介紹,我們都是使用Python3的。
1. 準(zhǔn)備操作,裝包,導(dǎo)入
雖然這非常簡單,但我們還是提一下。凡是做數(shù)據(jù)預(yù)處理,都不可避免的用上這兩個包。
import如果你要做基本的可視化,那還需要這個包
import這句語法的意思就是:導(dǎo)入...包,并給它命名為np/pd。很多人經(jīng)常在代碼中看到諸如np., pd. 這樣的前綴,意思就是調(diào)用numpy/pandas內(nèi)的函數(shù)(還有一個說法叫方法)。
網(wǎng)絡(luò)上有非常多關(guān)于這兩個包的命令詳解,百度一下都有。至于如何安裝,各位只需要百度一下anaconda即可。anaconda本身就可以理解為是一個封裝好的python環(huán)境,里面已經(jīng)事先有安裝好大部分必備的庫。
當(dāng)然,你也可以使用
pip有一個情況是你電腦里的默認python不是anaconda內(nèi)的那個(當(dāng)你電腦里裝了不止一個py的時候,這種情況是完全有可能的)。除了環(huán)境變量的優(yōu)先級調(diào)整法(具體的可以百度),還有一種方法我覺得更方便,就是打開anaconda的prompt。
這個Prompt可以理解為anaconda內(nèi)自己的cmd (command line)。那么這個時候,下面這一行代碼
就可以自動把你想要安裝的包安裝到你的anaconda中。對于我這種py底層機理一竅不通的人來說,這已經(jīng)夠用了,也很方便。雖然大部分情況都可以通過anaconda的可視化界面完成,但是我就碰到了tensorflow裝不上的情況,這個時候就只能采用上面那種方法了。
2. 讀取數(shù)據(jù),創(chuàng)建數(shù)據(jù)框
配置有了,下一步自然是讀取數(shù)據(jù),創(chuàng)建dataframe了。dataframe是pandas特有的一種數(shù)據(jù)結(jié)構(gòu),通俗理解就是一種計算機中存儲數(shù)據(jù)的結(jié)構(gòu),好吧這好像是一句廢話……
我截取了一部分我司的數(shù)據(jù)集(很顯然不可能是真實的,我在上面說過了),我們希望用它作為我們的例子,那么很顯然就需要構(gòu)造一個dataframe來存儲它。常見的操作就是先構(gòu)造一個字典,再轉(zhuǎn)換。具體如下
Table如果你運行正常的話,最后應(yīng)該可以看到這樣的結(jié)果。
(這是在Jupyter Notebook上運行的,如果你在別的IDE上運行,顯示的樣子可能會有些不一樣)相信通過這個例子你也大概明白了什么是一個dataframe。
注意:代碼pd.DataFrame()中是首字母大寫的。
注意:你也許看到了這么一行代碼
[這是列表生成式。比方說它的目的就是生成1-9的一個列表。如果把它拆分一下,就是這么一個意思
Aappend方法就是在已有的列表之后再尾插一個元素。range是一個迭代器,具體用法百度。
很顯然我們不會一直這么錄入數(shù)據(jù)的,實際的數(shù)據(jù)集一般都是很大的。這個時候一般都會讀取已有的大的.csv格式的數(shù)據(jù)集。一般使用
Table比方說如果要讀取上面的那個數(shù)據(jù)集,那么你的csv文件用excel打開應(yīng)該長這樣
.csv文件本質(zhì)上是用逗號分隔的文本文件,所以沒有xls/xlsx文件那么大。當(dāng)然了很多格式也無法保存在.csv文件中(比方說對一個數(shù)據(jù)標(biāo)紅,加粗等,這些格式都無法保存)。如果你用記事本打開.csv,文件是長這樣的,樸實而無華。
那么多逗號是因為我手動刪除了很多列……
最后說幾個參數(shù)
- encoding: 轉(zhuǎn)換編碼。這個在讀取我司的數(shù)據(jù)的時候尤其重要,因為外面的數(shù)據(jù)一般都很臟(意思就是處理不當(dāng)就是亂碼),所以強制為utf-8一定是墜吼的(最重要的是它對中文的支持非常好,所以數(shù)據(jù)看起來就很舒服)
- sep: 指定分隔符。因為有的文件可能會以tab為分隔符,這是為了防止出現(xiàn)一種情況就是表的內(nèi)容本身也存在逗號(比方說有人手賤把2019/6/1改成2019,6,1)。當(dāng)然一般的數(shù)據(jù)庫都沒這個處理,這個時候就只能手動來了……
- error_bad_lines: 這其實也是針對上面這種情況,因為如果識別逗號的時候發(fā)生錯誤,就會出現(xiàn)列名數(shù)和列數(shù)不一致的情況(比方說2019,6,1就會被拆成2019,6和1,本來是一個cell里的元素,硬是被拆到了3個cell里)。那么這個時候設(shè)置為False,系統(tǒng)就直接忽略這樣的行了。
在介紹下一個環(huán)節(jié)之前,我需要提一下的是我們的所有數(shù)據(jù)分析都會在本地進行。關(guān)于大數(shù)據(jù)架構(gòu)的相關(guān)內(nèi)容短時間并不會提到。
3. 數(shù)據(jù)拼接
雖然我們的數(shù)據(jù)非常小,但是實際情況下,數(shù)據(jù)因為過大很多時候在下載,提取的時候都會占用巨大的時間,因此很多時候我們都會分批次的下載。這種情況下我們自然需要把數(shù)據(jù)“拼”起來。如何去做呢?
Temppd.concat方法中的axis參數(shù)標(biāo)志的是行和列。比方說這里axis=0意思就是按行拼接,axis=1就是按列拼接了。當(dāng)然了,事先你需要把一些該拼起來的dataframe放在一個列表里。自然你還需要注意的是如果要按行拼接,那么自然兩個dataframe的列名,列數(shù)都是要相同的。另外一個同理。
當(dāng)然,如果你是純拼接的,這樣子當(dāng)然OK,但是很多時候,出現(xiàn)的情況是兩個待拼接的矩陣的列名有相同的地方。我們經(jīng)常會使用SQL提取我們想要的特征,不可能一個原始的表就能提供我們想要的所有信息,這個時候要在不同的數(shù)據(jù)表中提取,就會涉及到左連接,右連接,內(nèi)連接和外連接的情況。考慮到它們只是差別一個參數(shù)how,所以我們只解釋這四個名詞,就不舉例子了。
Definition 1: Left/Right/Inner/Outer Join左連接:表A, B連接只保留左表A的全部信息
右連接:表A, B連接只保留右表B的全部信息
內(nèi)連接:表A, B連接只保留兩表重合的信息
外連接:表A, B連接,除兩表重合的信息外,列按序全部保留
詳細的可以參考下面這篇文章
Pandas DataFrame連接表,幾種連接方法的對比?www.jianshu.com4. 數(shù)據(jù)篩選
如果對幾個簡單的命令不熟悉,那么這也是一個臟活。這里我們單獨舉幾個例子。
首先來看簡單列表情況的。
Example 1:找出列表中大于等于3的數(shù)據(jù),不改變表元素的順序
學(xué)過循環(huán)的人馬上開懷大笑,簡單!
B是,確實是一個不難的題目,可是Python有一個非常大的忌諱就是使用for循環(huán)。因為py的循環(huán)運行的很慢,所以實際我們的代碼中會盡量避免寫for循環(huán)(一般最多寫一重循環(huán),二重的說什么也得改成一重2333),所以如果數(shù)據(jù)量大一點,到了GB, TB級別的,這代碼就該傻眼了。之前我們說的列表生成式其實本質(zhì)上也是一種取代for循環(huán)的一個trick。
事實上,python有很多騷操作可以做一樣的事情。
Afilter函數(shù)就可以完成這個任務(wù),需要說明的是匿名函數(shù)lambda。你可以理解為filter就是把匿名函數(shù)施加到了每一個列表的元素中,達到“篩選”的目的。
如果是針對dataframe呢?我們用上面那個列表舉例子。
A很多人可能看不明白這個操作,我們看一下拆解代碼后的結(jié)果。
A也就是說,我們做的事情就是先通過邏輯表達式判斷T/F,然后用T/F去做篩選。
這樣子的話,又一個問題來了,我可不可以直接這樣做。
A雖然R語言是可以的,但是Python里面這樣做是需要一些預(yù)處理的。需要注意的是,這個操作如果針對的是pandas里的Series結(jié)構(gòu),那么是沒有問題的。但是針對dataframe是8行的……好,那么我們可不可以自己造一個Series呢?
A其實Series就是一個僅有一列的dataframe(但是嚴(yán)格意義上來說這是不對的,兩個數(shù)據(jù)結(jié)構(gòu)之間的方法,操作等是涇渭分明的)。
注意:一個很自然的聯(lián)想是,如果我希望選取一個區(qū)間,也就是說我需要兩個條件來制約。比方說我希望尋找值在[3, 4]的元素,那么有的人可能會寫成
A但事實上這是會報錯的。真正的寫法應(yīng)該是這樣
A1這個謎題至今我不知道為什么……征個解了,希望出沒在評論區(qū)的大佬可以解答~
至于提到針對Series結(jié)構(gòu)不太一樣的原因,我們之后再提,先放在這里。
除了這樣的邏輯關(guān)系篩選,其實還有一種篩選就是定點篩選。比方說下面這個業(yè)務(wù)需求。
Example 2:在A這個dataframe中挑選出值為2和3的所有元素。
注意這里的“值”的意思就是value,也就是除了index(最左邊那一列)外的其他列。
我們?nèi)绾螌崿F(xiàn)它呢?
A這里的.isin方法就需要我們提供一個列表,那么只要元素是這列表中的其中一個,就會被篩選出來。這個命令很多時候會很重要,比方說在推薦系統(tǒng)中,我們可能需要篩選出用戶中的高頻用戶,那么就可以通過邏輯關(guān)系篩選出這些用戶的ID,然后把ID的列表導(dǎo)出來,用這個列表去過濾原始的數(shù)據(jù)集,篩選出他們的銷售數(shù)據(jù)。
注意:你也許注意到了這個
A這個索引并沒有數(shù)量意義,這僅僅是因為A這個dataframe中,我們需要的那一列數(shù)據(jù)它的索引名是0(因為我們是直接把列表轉(zhuǎn)為了dataframe,所以默認索引為0)。也許你會想知道,那如果我希望知道dataframe的所有列名,怎么做呢?
A其實最重要的就是.columns這一個方法,其它的都是為了好看2333。另外這個也是只針對dataframe的(因為series是沒有header,也就是列名的)
你看,即使就是一個簡單的篩選,還有這么多細節(jié)的操作。
5. 數(shù)據(jù)整合
這一個部分主要是涉及到兩個操作,我們一個一個來看。
首先這第一個,其實是從這個業(yè)務(wù)需求來的。
Example 3:找出高頻用戶
你可能會想,這不是剛才已經(jīng)提到過了嗎?請注意我們是在業(yè)界,而業(yè)界的數(shù)據(jù)庫中往往并沒有直接提供你算法所使用的數(shù)據(jù)集。比方說在我司,能夠知道的就只有按照時間排列的每一筆的銷售數(shù)據(jù),但是如果你需要找到個人購買量,那就只能靠我們的整合代碼了。
我們顯然不會直接動用我司的數(shù)據(jù)集來演示。別忘了我們在第一個部分給大家手動創(chuàng)建了一個小的dataframe,我們就使用那個吧(變量名為Table)。
Table它的運行結(jié)果如下
這里我們用到的是groupby方法,也就是分組聚合。如果我們前面的列表生成式是對于每一個列表中的元素施加一個操作的話,這里的groupby就是針對dataframe中所選的那一列為“組名”來分組施加運算。比方說我們在原始的數(shù)據(jù)中,發(fā)現(xiàn)有2個人買了代號為S5的商品,那么你就可以看到,這兩個人就會對應(yīng)兩個訂單編號,兩個日期,等等,而count方法就是計數(shù)的,所以這一行都是2。
就這些了嗎?鬧太套!我不要你覺得,我要我覺得,這個問題不需要商量,都聽我的,完全不止這些!比方說下面這個
Table注意:這一行代碼有兩個點可以說:
- 因為我們是對一列以字符串為數(shù)據(jù)類型的數(shù)據(jù)求得和,在字符串意義下就是拼接。所以你可以看到,有兩個人買了S5,所以這兩個人對應(yīng)的商品代碼都是S5,拼在一起就變成了S5S5
- 你有沒有發(fā)現(xiàn)?如果我們事先提取我們所關(guān)心的那一列再進行求和,所對應(yīng)的結(jié)果就變成了一個Series結(jié)構(gòu)?還記得我們第四個部分說了什么嗎?沒有錯,在這個情況下,你可以發(fā)現(xiàn),我們的數(shù)據(jù)篩選也會變的簡單很多。
所以我們可以把篩選與整合結(jié)合起來,就可以完成我們下面這個業(yè)務(wù)需求了。
Example 4:過濾出購買超過一單的人對應(yīng)的所有訂單信息
我們還是使用Table這個數(shù)據(jù)集。
Temp雖然看上去四行代碼就完成我們的任務(wù)了,可是對于不熟練的人(比方說我),可能得摸索好幾天呢……
注意:如果你真的一步一步按照操作完成了,你會發(fā)現(xiàn)新的這個數(shù)據(jù)集它的索引并沒有變化,這樣的話如果你希望為數(shù)據(jù)添加特征(也就是添加幾列),可能會因為索引不匹配而報錯。所以一般推薦再加一行。
Result這樣就會重新從0開始按序排列索引。當(dāng)然如果你把drop參數(shù)設(shè)置成了F,那么原始的索引會被作為一列值,其列名為index,新的索引依然是從0開始。
說完groupby我們來說一下透視表。透視表其實可以理解為一種雙向groupby。也就是說,它相當(dāng)于選取了數(shù)據(jù)集的兩個特征做分組聚合。然后把這兩個特征的值作為兩個坐標(biāo)軸。具體的我們可以參考Table數(shù)據(jù)集的這個例子。
Example 5:構(gòu)造出一個以大分類為列,小分類為行的銷量數(shù)據(jù)。
它的代碼是這樣的
Resultpivot_table方法就是規(guī)定一列為新矩陣的列(index),一行為新矩陣的行(columns)。看似行列都有,結(jié)構(gòu)完整,可是值是不是有點問題?你看最上方那個order_id也能明白發(fā)生了什么,是吧?沒有錯,使用透視表的時候,如果使用np.sum,那么它會默認選擇一個數(shù)類別(比方說int)的列進行操作。可能有的人會覺得可不可以使用np.count/pd.count,可是人家沒有這個函數(shù)啊……
我自己的解決方法是多拼接一列全部為1的數(shù),然后再指定求和針對這一列。
Col可以看出來我們做了兩個改動,除了剛才說的拼接一列以外,還有一個就是我們多指定了函數(shù)中的values參數(shù),這就可以指定在哪一列進行操作。你可以看到,新的數(shù)據(jù)集中值均正確,也沒有多出詭異的一個頭。
注意:pd.concat只可以拼接dataframe,所以如果是numpy的array,就需要做一步轉(zhuǎn)換了。為了方便我們索引,我們給它加了一個列名(.columns方法)
值得一提的函數(shù)是np.tile,它的機理是對已有的列表,矩陣進行不同軸上的復(fù)制粘貼。舉個例子,生成一個全1的長度為10列向量,其本質(zhì)就是一個1,然后按列方向復(fù)制粘貼了10次,對吧?比方說下面這個例子
A你也可以看到,在numpy中構(gòu)造矩陣的方式就是先構(gòu)造一個向量,然后用reshape方法去重塑它的結(jié)構(gòu)。這里np.tile這相當(dāng)于一個小矩陣行列各擴充為原來的兩倍。感興趣的人可以試試把它轉(zhuǎn)為dataframe,看看它的索引,列名是什么?
最后關(guān)于透視表的其它操作可以參考這個官方文檔。
pandas.DataFrame.pivot_table - pandas 0.25.1 documentation?pandas.pydata.org6. 數(shù)據(jù)刪除
如果僅僅是說選取一個區(qū)間內(nèi)的子集,這個我相信沒必要單獨拉出來說,直接用pandas內(nèi)的數(shù)量索引就好。但是如果希望刪去指定行列呢?比方說剛才那個Table數(shù)據(jù)集,我們希望把那個多余的全1向量刪去,怎么辦?
Table這樣就可以復(fù)原了。注意這里axis = 1表示考慮列名,而不是索引。
7. 數(shù)據(jù)導(dǎo)出
顯然,我們還需要把我們做好處理的文件再導(dǎo)出為一個csv,這在py中也不難做到。
Resultheader和index就是表頭(列名)和索引,如果均選擇T,那么就會顯示出它們,否則就只會顯示出這些值所構(gòu)成的矩陣了。
注意:在保存文件的時候要注意你選擇的工作路徑。因為如果路徑不是絕對路徑,那么保存的時候就會保存在你的工作路徑下。
小結(jié)
在這一節(jié)我們主要介紹了py中一些相對比較常見,但是又有一些小難度的實際數(shù)據(jù)分析中需要使用的python操作集合。所有的總結(jié)均是個人摸索的操作,因此具有很強的主觀性。我非常希望能夠有py大佬在評論區(qū),或者私信,對不同的業(yè)務(wù)需求提出更好的解決方案!也希望和我一樣的數(shù)據(jù)分析新手能夠從中受益~
下一篇筆記傳送門:Python|專題(2)——數(shù)據(jù)處理常規(guī)操作集(2),數(shù)值計算的幾個加速技巧
——————————————————————————————————————
本專欄為我的個人專欄,也是我學(xué)習(xí)筆記的主要生產(chǎn)地。任何筆記都具有著作權(quán),不可隨意轉(zhuǎn)載和剽竊。
個人微信公眾號:cha-diary,你可以通過它來獲得最新文章更新的通知。
《一個大學(xué)生的日常筆記》專欄目錄:筆記專欄|目錄
《GetDataWet》專欄目錄:GetDataWet|目錄
想要更多方面的知識分享嗎?可以關(guān)注專欄:一個大學(xué)生的日常筆記。你既可以在那里找到通俗易懂的數(shù)學(xué),也可以找到一些雜談和閑聊。也可以關(guān)注專欄:GetDataWet,看看在大數(shù)據(jù)的世界中,一個人的心路歷程。我鼓勵和我相似的同志們投稿于此,增加專欄的多元性,讓更多相似的求知者受益~
總結(jié)
以上是生活随笔為你收集整理的python如何从一个dataframe提取相应的行组成一个新的dataframe_Python|专题(1)——数据处理常规操作集(1)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: csv文件怎么转成excel_怎么把wo
- 下一篇: 爬虫 404 try_无所不能的Pyth