整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          前端:JS延長加載的方式有哪些?

          么是JS延遲加載?

          JS延遲加載,也就是等頁面加載完成之后再加載JavaScript文件

          為什么讓JS實現延遲加載?

          js的延遲加載有助于提高頁面的加載速度。

          Js延遲加載的方式有哪些?一般有以下幾種方式:

          ·defer屬性

          ·async屬性

          ·動態創建DOM方式

          ·使用jQuery的getScript方法

          ·使用setTimeout延遲方法

          ·讓JS最后加載

          1、defer屬性

          HTML 4.01為<script>標簽定義了defer屬性。標簽定義了defer屬性元素中設置defer屬性,等于告訴瀏覽器立即下載,但延遲執行標簽定義了defer屬性。

          用途:表明腳本在執行時不會影響頁面的構造。也就是說,腳本會被延遲到整個頁面都解析完畢之后再執行在<script>元素中設置defer屬性,等于告訴瀏覽器立即下載,但延遲執行

          <!DOCTYPE html>
          <html>
          <head>
          	<script src="test1.js" defer="defer"></script>
          	<script src="test2.js" defer="defer"></script>
          </head>
          <body>
          <!--這里放內容-->
          </body>
          </html>

          說明:雖然<script>元素放在了<head>元素中,但包含的腳本將延遲瀏覽器遇到</html>標簽后再執行HTML5規范要求腳本按照它們出現的先后順序執行。在現實當中,延遲腳本并不一定會按照順序執行defer屬性只適用于外部腳本文件。支持HTML5的實現會忽略嵌入腳本設置的defer屬性

          2、async屬性

          HTML5 為<script>標簽定義了async屬性。與defer屬性類似,都用于改變處理腳本的行為。同樣,只適用于外部腳本文件。標簽定義了async屬性。與defer屬性類似,都用于改變處理腳本的行為。同樣,只適用于外部腳本文件。

          目的:不讓頁面等待腳本下載和執行,從而異步加載頁面其他內容。異步腳本一定會在頁面 load 事件前執行。不能保證腳本會按順序執行

          <!DOCTYPE html>
          <html>
          	<head>
          		<script src="test1.js" async></script>
          		<script src="test2.js" async></script>
          	</head>
          <body>
          <!--這里放內容-->
          </body>
          </html>

          async和defer一樣,都不會阻塞其他資源下載,所以不會影響頁面的加載。

          缺點:不能控制加載的順序

          3、動態創建DOM方式

          //這些代碼應被放置在</ body>標簽前(接近HTML文件底部)
          <script type="text/javascript">
          	function downloadJSAtOnload() {
          		varelement = document .createElement("script");
          		element.src = "defer.js";
          		document.body.appendChild(element);
          	}
          	if (window. addEventListener)
          		window.addEventListener("load" ,downloadJSAtOnload, false);
          	else if (window.attachEvent)
          		window.attachEvent("onload", downloadJSAtOnload) ;
          	else
          		window. onload =downloadJSAtOnload;
          </script>

          4、使用jQuery的getScript()方法

          $.getScript("outer.js" , function(){	//回調函數,成功獲取文件后執行的函數
          	console.log(“腳本加載完成")
          });

          5、使用setTimeout延遲方法的加載時間延遲加載js代碼,給網頁加載留出更多時間

          <script type="text/javascript" >
          	function A(){
          		$.post("/1ord/1ogin" ,{name:username,pwd:password},function(){
          			alert("Hello");
          		});
          	}
          	$(function (){
          		setTimeout('A()', 1000);	//延遲1秒
          	})
          </script>

          6、讓JS最后加載

          把js外部引入的文件放到頁面底部,來讓js最后引入,從而加快頁面加載速度例如引入外部js腳本文件時,如果放入html的head中,則頁面加載前該js腳本就會被加載入頁面,而放入body中,則會按照頁面從上倒下的加載順序來運行JavaScript的代碼。所以我們可以把js外部引入的文件放到頁面底部,來讓js最后引入,從而加快頁面加載速度。

          上述方法2也會偶爾讓你收到Google頁面速度測試工具的“延遲加載javascript”警告。所以這里的解決方案將是來自Google幫助頁面的推薦方案。

          //這些代碼應被放置在</body>標簽前(接近HTML文件底部)
          
          <script type= "text/javascript">
          	function downloadJSAtonload() {
          		var element = document.createElement("script");
          		element.src = "defer.js";
          		document.body.appendChild(element);
          	}
          	if (window.addEventListener)
          		window.addEventListener("load", downloadJSAtOnload, false);
          	else if (window.attachEvent )
          		window.attachEvent("onload", downloadJSAtonload);
          	else window.onload = downloadJSAtOnload;
          </script>

          這段代碼意思等到整個文檔加載完后,再加載外部文件“defer.js”。

          使用此段代碼的步驟:

          6.1)復制上面代碼

          6.2)粘貼代碼到HTML的標簽前 (靠近HTML文件底部)

          6.3)修改“defer.js”為你的外部JS文件名

          6.4)確保文件路徑是正確的。例如:如果你僅輸入“defer.js”,那么“defer.js”文件一定與HTML文件在同一文件夾下。

          注意:

          這段代碼直到文檔加載完才會加載指定的外部js文件。因此,不應該把那些頁面正常加載需要依賴的javascript代碼放在這里。而應該將JavaScript代碼分成兩組。一組是因頁面需要而立即加載的javascript代碼,另外一組是在頁面加載后進行操作的javascript代碼(例如添加click事件。

          x1 工具準備

          工欲善其事必先利其器,爬取語料的根基便是基于python。

          我們基于python3進行開發,主要使用以下幾個模塊:requests、lxml、json。

          簡單介紹一個各模塊的功能

          01|requests

          requests是一個Python第三方庫,處理URL資源特別方便。它的官方文檔上寫著大大口號:HTTP for Humans(為人類使用HTTP而生)。相比python自帶的urllib使用體驗,筆者認為requests的使用體驗比urllib高了一個數量級。

          我們簡單的比較一下:

          urllib:

           1import urllib2
           2import urllib
           3
           4URL_GET = "https://api.douban.com/v2/event/list"
           5#構建請求參數
           6params = urllib.urlencode({'loc':'108288','day_type':'weekend','type':'exhibition'})
           7
           8#發送請求
           9response = urllib2.urlopen('?'.join([URL_GET,'%s'])%params)
          10#Response Headers
          11print(response.info())
          12#Response Code
          13print(response.getcode())
          14#Response Body
          15print(response.read())
          復制代碼
          

          requests:

           1import requests
           2
           3URL_GET = "https://api.douban.com/v2/event/list"
           4#構建請求參數
           5params = {'loc':'108288','day_type':'weekend','type':'exhibition'}
           6
           7#發送請求
           8response = requests.get(URL_GET,params=params)
           9#Response Headers
          10print(response.headers)
          11#Response Code
          12print(response.status_code)
          13#Response Body
          14print(response.text)復制代碼
          

          我們可以發現,這兩種庫還是有一些區別的:

          1. 參數的構建:urllib需要對參數進行urlencode編碼處理,比較麻煩;requests無需額外編碼處理,十分簡潔。

          2. 請求發送:urllib需要額外對url參數進行構造,變為符合要求的形式;requests則簡明很多,直接get對應鏈接與參數。

          3. 連接方式:看一下返回數據的頭信息的“connection”,使用urllib庫時,"connection":"close",說明每次請求結束關掉socket通道,而使用requests庫使用了urllib3,多次請求重復使用一個socket,"connection":"keep-alive",說明多次請求使用一個連接,消耗更少的資源

          4. 編碼方式:requests庫的編碼方式Accept-Encoding更全,在此不做舉例

          綜上所訴,使用requests更為簡明、易懂,極大的方便我們開發。

          02|lxml

          BeautifulSoup是一個庫,而XPath是一種技術,python中最常用的XPath庫是lxml。

          當我們拿到requests返回的頁面后,我們怎么拿到想要的數據呢?這個時候祭出lxml這強大的HTML/XML解析工具。python從不缺解析庫,那么我們為什么要在眾多庫里選擇lxml呢?我們選擇另一款出名的HTML解析庫BeautifulSoup來進行對比。

          我們簡單的比較一下:

          BeautifulSoup:

          1from bs4 import BeautifulSoup #導入庫
          2# 假設html是需要被解析的html
          3
          4#將html傳入BeautifulSoup 的構造方法,得到一個文檔的對象
          5soup = BeautifulSoup(html,'html.parser',from_encoding='utf-8')
          6#查找所有的h4標簽 
          7links = soup.find_all("h4")
          復制代碼
          

          lxml:

          1from lxml import etree
          2# 假設html是需要被解析的html
          3
          4#將html傳入etree 的構造方法,得到一個文檔的對象
          5root = etree.HTML(html)
          6#查找所有的h4標簽 
          7links = root.xpath("http://h4")
          復制代碼
          

          我們可以發現,這兩種庫還是有一些區別的:

          1. 解析html: BeautifulSoup的解析方式和JQ的寫法類似,API非常人性化,支持css選擇器;lxml的語法有一定的學習成本

          2. 性能:BeautifulSoup是基于DOM的,會載入整個文檔,解析整個DOM樹,因此時間和內存開銷都會大很多;而lxml只會局部遍歷,另外lxml是用c寫的,而BeautifulSoup是用python寫的,明顯的性能上lxml>>BeautifulSoup。

          綜上所訴,使用BeautifulSoup更為簡明、易用,lxml雖然有一定學習成本,但總體也很簡明易懂,最重要的是它基于C編寫,速度快很多,對于筆者這種強迫癥,自然而然就選lxml啦。

          03|json

          python自帶json庫,對于基礎的json的處理,自帶庫完全足夠。但是如果你想更偷懶,可以使用第三方json庫,常見的有demjson、simplejson。

          這兩種庫,無論是import模塊速度,還是編碼、解碼速度,都是simplejson更勝一籌,再加上兼容性 simplejson 更好。所以大家如果想使用方庫,可以使用simplejson。

          0x2 確定語料源

          將武器準備好之后,接下來就需要確定爬取方向。

          以電競類語料為例,現在我們要爬電競類相關語料。大家熟悉的電競平臺有企鵝電競、企鵝電競和企鵝電競(斜眼),所以我們以企鵝電競上直播的游戲作為數據源進行爬取。

          我們登陸企鵝電競官網,進入游戲列表頁,可以發現頁面上有很多游戲,通過人工去寫這些游戲名收益明顯不高,于是我們就開始我們爬蟲的第一步:游戲列表爬取。


           1import requests
           2from lxml import etree
           3
           4# 更新游戲列表
           5def _updateGameList():
           6 # 發送HTTP請求時的HEAD信息,用于偽裝為瀏覽器
           7 heads = { 
           8 'Connection': 'Keep-Alive',
           9 'Accept': 'text/html, application/xhtml+xml, */*',
          10 'Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3',
          11 'Accept-Encoding': 'gzip, deflate',
          12 'User-Agent': 'Mozilla/6.1 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko'
          13 }
          14 # 需要爬取的游戲列表頁
          15 url = 'https://egame.qq.com/gamelist'
          16
          17 # 不壓縮html,最大鏈接時間為10妙
          18 res = requests.get(url, headers=heads, verify=False, timeout=10)
          19 # 為防止出錯,編碼utf-8
          20 res.encoding = 'utf-8'
          21 # 將html構建為Xpath模式
          22 root = etree.HTML(res.content)
          23 # 使用Xpath語法,獲取游戲名
          24 gameList = root.xpath("http://ul[@class='livelist-mod']//li//p//text()")
          25 # 輸出爬到的游戲名
          26 print(gameList)
          復制代碼
          

          當我們拿到這幾十個游戲名后,下一步就是對這幾十款游戲進行語料爬取,這時候問題就來了,我們要從哪個網站來爬這幾十個游戲的攻略呢,taptap?多玩?17173?在對這幾個網站進行分析后,發現這些網站僅有一些熱門游戲的文章語料,一些冷門或者低熱度的游戲,例如“靈魂籌碼”、“奇跡:覺醒”、“死神來了”等,很難在這些網站上找到大量文章語料,如圖所示:

          我們可以發現,“ 奇跡:覺醒”、“靈魂籌碼”的文章語料特別少,數量上不符合我們的要求。 那么有沒有一個比較通用的資源站,它擁有著無比豐富的文章語料,可以滿足我們的需求。

          其實靜下心來想想,這個資源站我們天天都有用到,那就是百度。我們在百度新聞搜索相關游戲,拿到搜索結果列表,這些列表的鏈接的網頁內容幾乎都與搜索結果強相關,這樣我們數據源不夠豐富的問題便輕松解決了。但是此時出現了一個新的問題,并且是一個比較難解決的問題——如何抓取到任意網頁的文章內容?

          因為不同的網站都有不同的頁面結構,我們無法與預知將會爬到哪個網站的數據,并且我們也不可能針對每一個網站都去寫一套爬蟲,那樣的工作量簡直難以想象!但是我們也不能簡單粗暴的將頁面中的所有文字都爬下來,用那樣的語料來進行訓練無疑是噩夢!

          經過與各個網站斗智斗勇、查詢資料與思索之后,終于找到一條比較通用的方案,下面為大家講一講筆者的思路。

          0x3 任意網站的文章語料爬取

          01|提取方法

          1)基于Dom樹正文提取

          2)基于網頁分割找正文塊

          3)基于標記窗的正文提取

          4)基于數據挖掘或機器學習

          5)基于行塊分布函數正文提取

          02|提取原理

          大家看到這幾種是不是都有點疑惑了,它們到底是怎么提取的呢?讓筆者慢慢道來。

          1)基于Dom樹的正文提取:

          這一種方法主要是通過比較規范的HTML建立Dom樹,然后地柜遍歷Dom,比較并識別各種非正文信息,包括廣告、鏈接和非重要節點信息,將非正文信息抽離之后,余下來的自然就是正文信息。

          但是這種方法有兩個問題

          ① 特別依賴于HTML的良好結構,如果我們爬取到一個不按W3c規范的編寫的網頁時,這種方法便不是很適用。

          ② 樹的建立和遍歷時間復雜度、空間復雜度都較高,樹的遍歷方法也因HTML標簽會有不同的差異。

          2) 基于網頁分割找正文塊 :

          這一種方法是利用HTML標簽中的分割線以及一些視覺信息(如文字顏色、字體大小、文字信息等)。

          這種方法存在一個問題:

          ① 不同的網站HTML風格迥異,分割沒有辦法統一,無法保證通用性。

          3) 基于標記窗的正文提取:

          先科普一個概念——標記窗,我們將兩個標簽以及其內部包含的文本合在一起成為一個標記窗(比如 <h1>我是h1</h1> 中的“我是h1”就是標記窗內容),取出標記窗的文字。

          這種方法先取文章標題、HTML中所有的標記窗,在對其進行分詞。然后計算標題的序列與標記窗文本序列的詞語距離L,如果L小于一個閾值,則認為此標記窗內的文本是正文。

          這種方法雖然看上去挺好,但其實也是存在問題的:

          ① 需要對頁面中的所有文本進行分詞,效率不高。

          ② 詞語距離的閾值難以確定,不同的文章擁有不同的閾值。

          4)基于數據挖掘或機器學習

          使用大數據進行訓練,讓機器提取主文本。

          這種方法肯定是極好的,但是它需要先有html與正文數據,然后進行訓練。我們在此不進行探討。

          5)基于行塊分布函數正文提取

          對于任意一個網頁,它的正文和標簽總是雜糅在一起。此方法的核心有亮點:① 正文區的密度;② 行塊的長度;一個網頁的正文區域肯定是文字信息分布最密集的區域之一,這個區域可能最大(評論信息長、正文較短),所以同時引進行塊長度進行判斷。

          實現思路:

          ① 我們先將HTML去標簽,只留所有正文,同時留下標簽取出后的所有空白位置信息,我們稱其為Ctext;

          ② 對每一個Ctext取周圍k行(k<5),合起來稱為Cblock;

          ③ 對Cblock去掉所有空白符,其文字總長度稱為Clen;

          ④ 以Ctext為橫坐標軸,以各行的Clen為縱軸,建立坐標系。

          以這個網頁為例: http://www.gov.cn/ldhd/2009-11/08/content_1459564.htm 該網頁的正文區域為145行至182行。


          由上圖可知,正確的文本區域全都是分布函數圖上含有最值且連續的一個區域,這個區域往往含有一個驟升點和一個驟降點。因此,網頁正文抽取問題轉化為了求行塊分布函數上的驟升點和驟降點兩個邊界點,這兩個邊界點所含的區域包含了當前網頁的行塊長度最大值并且是連續的。

          經過大量實驗,證明此方法對于中文網頁的正文提取有較高的準確度,此算法的優點在于,行塊函數不依賴與HTML代碼,與HTML標簽無關,實現簡單,準確率較高。

          主要邏輯代碼如下:

           1# 假設content為已經拿到的html
           2
           3# Ctext取周圍k行(k<5),定為3
           4blocksWidth = 3
           5# 每一個Cblock的長度
           6Ctext_len = []
           7# Ctext
           8lines = content.split('n')
           9# 去空格
          10for i in range(len(lines)):
          11 if lines[i] == ' ' or lines[i] == 'n':
          12 lines[i] = ''
          13# 計算縱坐標,每一個Ctext的長度
          14for i in range(0, len(lines) - blocksWidth):
          15 wordsNum = 0
          16 for j in range(i, i + blocksWidth):
          17 lines[j] = lines[j].replace("\s", "")
          18 wordsNum += len(lines[j])
          19 Ctext_len.append(wordsNum)
          20# 開始標識
          21start = -1
          22# 結束標識
          23end = -1
          24# 是否開始標識
          25boolstart = False
          26# 是否結束標識
          27boolend = False
          28# 行塊的長度閾值
          29max_text_len = 88
          30# 文章主內容
          31main_text = []
          32# 沒有分割出Ctext
          33if len(Ctext_len) < 3:
          34 return '沒有正文'
          35for i in range(len(Ctext_len) - 3):
          36 # 如果高于這個閾值
          37 if(Ctext_len[i] > max_text_len and (not boolstart)):
          38 # Cblock下面3個都不為0,認為是正文
          39 if (Ctext_len[i + 1] != 0 or Ctext_len[i + 2] != 0 or Ctext_len[i + 3] != 0):
          40 boolstart = True
          41 start = i
          42 continue
          43 if (boolstart):
          44 # Cblock下面3個中有0,則結束
          45 if (Ctext_len[i] == 0 or Ctext_len[i + 1] == 0):
          46 end = i
          47 boolend = True
          48 tmp = []
          49
          50 # 判斷下面還有沒有正文
          51 if(boolend):
          52 for ii in range(start, end + 1):
          53 if(len(lines[ii]) < 5):
          54 continue
          55 tmp.append(lines[ii] + "n")
          56 str = "".join(list(tmp))
          57 # 去掉版權信息
          58 if ("Copyright" in str or "版權所有" in str):
          59 continue
          60 main_text.append(str)
          61 boolstart = boolend = False
          62# 返回主內容
          63result = "".join(list(main_text))
          復制代碼
          

          0x4 結語

          至此我們就可以獲取任意內容的文章語料了,但這僅僅是開始,獲取到了這些語料后我們還需要在一次進行清洗、分詞、詞性標注等,才能獲得真正可以使用的語料。

          本篇文章主要介紹了pandas中對series和dataframe對象進行連接的方法:pd.append()和pd.concat(),文中通過示例代碼對這兩種方法進行了詳細的介紹,希望能對各位python小白的學習有所幫助。

          一、df.append(df)

          ? 描述:append方法用以在表尾中添加新的行,并返回追加后的數據對象,若追加的行中存在原數據沒有的列,會新增一列,并用nan填充;若追加的行數據中缺少原數據某列,同樣以nan填充

          語法:df.append(other, ignore_index=False, verify_integrity=False, sort=None)

          ? 參數說明:

          • other:要追加的數據,可以是dataframe,series,字典,列表
          • ignore_index:兩個表的index是否有實際含義,默認為False,若ignore_index=True,表根據列名對齊合并,生成新的index
          • verify_integrity:默認為False,若為True,創建具有重復項的索引時引發ValueError
          • sort:默認為False,若為True如果’ self ‘和’ other '的列沒有對齊,則對列進行排序。

          下面對append方法的每個參數進行詳細介紹:

          ? 第一個參數為other:要追加的數據,可以是dataframe,series,字典,列表甚至是元素;但前后類型要一致。

          1. 將數據追加到series
          # 將數據追加到series
          <<< a=df.iloc[0,:]
          <<< b=df.iloc[6,:]
          <<< a.append(b)      #需賦給新值,不改變原數組
          A     0
          B     1
          C     2
          D     3
          E     4
          F     5
          A    36
          B    37
          C    38
          D    39
          E    40
          F    41
          dtype: int32
          <<< a
          A    0
          B    1
          C    2
          D    3
          E    4
          F    5
          Name: S1, dtype: int32
          
          <<< c=a.append(b)    # 保存為c
          <<< c
          A     0
          B     1
          C     2
          D     3
          E     4
          F     5
          A    36
          B    37
          C    38
          D    39
          E    40
          F    41
          dtype: int32
          
          1. 將數據追加到dataframe
          # 將數據追加到dataframe
          <<< a=df.iloc[0:2,:]
          <<< b=df.iloc[4:6,:] 
          <<< c=a.append(b)           # 注意是縱向追加,不支持橫向追加
          <<< c
              A	B	C	D	E   F
          S1	0	1	2	3	4	5
          S2	6	7	8	9	10	11
          S5	24	25	26	27	28	29
          S6	30	31	32	33	34	35
          

          ? 注意:獲取單行得到的結果是一維數組,當一維數組[6,:]和二維數組[2,6]追加時,會得到8*7的數組,匹配不上的地方用NA填充。

          # 將二維數組追加到一維數組
          <<< a=df.iloc[0,:]
          <<< b=df.iloc[4:6,:] 
          <<< c=a.append(b)          
          <<< c
                0	  A	  B	  C	  D	  E	  F
          A	0.0	NaN	NaN	NaN	NaN	NaN	NaN
          B	1.0	NaN	NaN	NaN	NaN	NaN	NaN
          C	2.0	NaN	NaN	NaN	NaN	NaN	NaN
          D	3.0	NaN	NaN	NaN	NaN	NaN	NaN
          E	4.0	NaN	NaN	NaN	NaN	NaN	NaN
          F	5.0	NaN	NaN	NaN	NaN	NaN	NaN
          S5	NaN	24.0	25.0	26.0	27.0	28.0	29.0
          S6	NaN	30.0	31.0	32.0	33.0	34.0	35.0
          
          1. 將數據追加到list
          • list是一維:以列的形式來進行追加操作
          • list是二維:以行的形式來進行追加操作
          • list是三維:只添加一個值注意:追加到列表時,是在原數組改動,是在原數組改動,是在原數組改動
          # 列表追加到列表
          <<< a=[]
          <<< b=df.iloc[6,:].tolist()
          <<< a.append(b)
          <<< a
          [[36, 37, 38, 39, 40, 41]]
          
          # 序列追加到列表
          <<< a=[1,2,3,4,5,6,7]
          <<< b=df.iloc[6,:]
          <<< a.append(b)
          <<< a
          [1, 2, 3, 4, 5, 6, 7, A    36
           B    37
           C    38
           D    39
           E    40
           F    41
           Name: S7, dtype: int32]
          
          1. 追加字典TypeError: Can only append a Series if ignore_index=True or if the Series has a name
          <<< df1=pd.DataFrame()
          <<< a={'A':1,'B':2}
          <<< df1=df1.append(a,ignore_index=True)
          <<< df1
              A	B
          0	1	2
          
          1. 將單個元素追加到列表

          ? append方法也可以將單個元素追加到列表(其他對象不行),會自動將單個元素轉為列表對象,再進行追加操作

          # 單個元素進行追加
          <<< a=[1,2,3,4,5,6,7,8]
          <<< a.append(9)
          <<< a
          [1, 2, 3, 4, 5, 6, 7, 8, 9]
          
          1. 將其他類型對象追加到dataframe當dataframe使用append方法添加series或字典的時候,必須要設置name,設置name名稱將會作為index的name,否則會報錯提示:TypeError: Can only append a Series if ignore_index=True or if the Series has a name
          <<< df1=pd.DataFrame()
          <<< ser=pd.Series({"x":1,"y":2},name="a")
          <<< df1=df1.append(ser)
          <<< df1
              x   y
          a	1	2
          

          ? 如果不添加name,也可以添加參數ignore_index:

          <<< df1=pd.DataFrame()
          <<< ser=pd.Series({"x":1,"y":2})
          <<< df1=df1.append(ser,ignore_index=True)
          <<< df1
              x   y
          a	1	2
          

          ? 第二個參數:兩個表的index是否有實際含義,默認ignore_index=False,若為True,表根據列名對齊合并,生成新的index。

          <<< a=df.iloc[0:2,:]
          <<< b=df.iloc[4:6,:]
          <<< a.append(b,ignore_index=True)  
              A   B	C   D   E   F
          0	0	1	2	3	4	5
          1	6	7	8	9	10	11
          2	24	25	26	27	28	29
          3	30	31	32	33	34	35
          
          <<< a=df.iloc[0:2,:]
          <<< b=df.iloc[4:6,:]
          <<< a.append(b)
              A	B	C	D	E   F
          S1	0	1	2	3	4	5
          S2	6	7	8	9	10	11
          S5	24	25	26	27	28	29
          S6	30	31	32	33	34	35
          

          ? 在dataframe中,使用append方法進行表合并時,二者匹配不上的地方用NAN填充。

          <<< df1=df.copy()
          <<< df2=pd.DataFrame(np.arange(8).reshape(2,4),columns=<<<['s1','s2','s3','s4'])
          <<< df_new=df1.append(df2,ignore_index=True)
          <<< df_new
              A	B	C	D	E	F	S1	S2	s3	s4
          0	0	1	2	3	4	5	NaN	NaN	NaN	NaN
          1	6	7	8	9	10	11	NaN	NaN	NaN	NaN
          2	12	13	14	15	16	17	NaN	NaN	NaN	NaN
          3	18	19	20	21	22	23	NaN	NaN	NaN	NaN
          4	24	25	26	27	28	29	NaN	NaN	NaN	NaN
          5	30	31	32	33	34	35	NaN	NaN	NaN	NaN
          6	36	37	38	39	40	41	NaN	NaN	NaN	NaN
          7	NaN	NaN	NaN	NaN	NaN	NaN	0	1	2	3
          8	NaN	NaN	NaN	NaN	NaN	NaN	4	5	6	7
          

          ? 第三個參數為verify_integrity:默認為False 參數用于檢查結果對象新連接軸上的索引是否有重復項,有的話引發 ValueError,可以看到這個參數的作用與ignore_index 是互斥的。 (如果 ignore_index = True ,則意味著index不能是重復的,而ignore_index = False ,則意味著index可以是重復的)

          <<< df1=df.copy()
          <<< df2=pd.DataFrame(np.arange(8).reshape(2,4),columns=   <<< ['G','H','I','J'],index=['S1','S8'],dtype=int)
          <<< pd.set_option('precision',0)
          <<< df_new=df1.append(df2,verify_integrity=False)
          <<< df_new
              A	B	C	D	E	F	G	H	I	J
          S1	0	1	2	3	4	5	NaN	NaN	NaN	NaN
          S2	6	7	8	9	10	11	NaN	NaN	NaN	NaN
          S3	12	13	14	15	16	17	NaN	NaN	NaN	NaN
          S4	18	19	20	21	22	23	NaN	NaN	NaN	NaN
          S5	24	25	26	27	28	29	NaN	NaN	NaN	NaN
          S6	30	31	32	33	34	35	NaN	NaN	NaN	NaN
          S7	36	37	38	39	40	41	NaN	NaN	NaN	NaN
          S1	NaN	NaN	NaN	NaN	NaN	NaN	0	1	2	3
          S8	NaN	NaN	NaN	NaN	NaN	NaN	4	5	6	7
          

          注意:當需要連接的兩個表的index有重復值時,設置ignore_index = True則會報錯。

          ? 第四個參數為sort:默認是False,該屬性在pandas的0.23.0版本才有,若為True,則對兩個表沒匹配上的列名,進行排序,若為False,不排序。

          <<< df1=pd.DataFrame(np.arange(8).reshape(2,4),columns=   <<< ['A1','B1','C1','D1'],index=['S1','S2'])
          <<< df2=pd.DataFrame(np.arange(8).reshape(2,4),columns=   <<< ['A2','B2','C2','D2'],index=['S1','S3'])
          <<< pd.set_option('precision',0)
          <<< df_new=df1.append(df2,sort=True)
          <<< df_new
              A1	A2	B1	B2	C1	C2	D1	D2
          S1	0	NaN	1	NaN	2	NaN	3	NaN
          S2	4	NaN	5	NaN	6	NaN	7	NaN
          S1	NaN	0	NaN	1	NaN	2	NaN	3
          S3	NaN	4	NaN	5	NaN	6	NaN	7
          

          二、pd.concat([df_01,df_02])

          ? 描述:concat方法用以將兩個或多個pandas對象根據軸(橫向/縱向)進行拼接,concat函數是在pandas命名空間下的方法,因此需要通過pd.concat()的方式來引用。

          語法:pd.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’)

          常用參數:

          • objs:要進行拼接的pandas對象,可用中括號[]將兩個或多個對象括起來
          • axis:指定對象按照那個軸進行拼接,默認為0(縱向拼接),1為橫向橫向拼接
          • join:拼接的方式,inner為交集,outer為并集
          • join_axes:index的列表,僅在橫向合并時使用,指明要將數據合并入哪個原表的index。
          • ignore_index:默認為False,如果設置為true,則無視表原來的軸標簽,直接合并,合并后生成新的軸標簽。
          • keys:表標識的列表,用來區分合并的表來自哪里。

          下面,將對concat方法以上各個參數進行詳細說明:

          ? 第一個要學習的參數為objs:要進行拼接的pandas對象,可用中括號[]將兩個或多個對象括起來。

          1)對series進行拼接

          <<< ser1=pd.Series(np.arange(9))
          <<< ser2=pd.Series(np.arange(9))
          # 對兩個series對象進行拼接
          <<< pd.concat([ser1,ser2])
          0    0
          1    1
          2    2
          3    3
          4    4
          5    5
          6    6
          7    7
          8    8
          0    0
          1    1
          2    2
          3    3
          4    4
          5    5
          6    6
          7    7
          8    8
          dtype: int32
          
          1. 對DataFrame進行拼接
          <<< df1=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['A','B','C'],index=['a','b','c'])
          <<< df2=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['D','E','F'],index=['e','f','g'])
          # 對兩個DataFrame對象進行拼接
          <<< pd.concat([df1,df2])
              A   B	C	D	E   F
          a	0	1	2	NaN	NaN	NaN
          b	3	4	5	NaN	NaN	NaN
          c	6	7	8	NaN	NaN	NaN
          e	NaN	NaN	NaN	0	1	2
          f	NaN	NaN	NaN	3	4	5
          g	NaN	NaN	NaN	6	7	8
          

          ? 第二個要學習的參數為axis:指定對象按照那個軸進行拼接,默認為0(縱向拼接),1為橫向橫向拼接。

          <<< df1=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['A','B','C'],index=['a','b','c'])
          <<< df2=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['D','E','F'],index=['a','b','d'])
          # 將數據對象df1和df2沿1軸進行拼接,即進行橫向拼接
          <<< pd.concat([df1,df2],axis=1)
              A	B	C	D	E	F
          a	0	1	2	0	1	2
          b	3	4	5	3	4	5
          c	6	7	8	NaN	NaN	NaN
          d	NaN	NaN	NaN	6	7	8
          

          ? 注意:當對Series進行拼接時,設置axis=0進行縱向拼接的結果對象為Series,設置axis=1進行橫向拼接的結果對象為DataFrame。

          <<< ser1=pd.Series(np.arange(9))
          <<< ser2=pd.Series(np.arange(9))
          # 對Series進行拼接縱向拼接,結果認為Series對象
          <<< a=pd.concat([ser1,ser2],axis=0)
          <<< type(a)
          pandas.core.series.Series
          # 對Series進行拼接橫向拼接,結果轉換為DataFrame對象
          <<< b=pd.concat([ser1,ser2],axis=1)
          <<< type(b)
          pandas.core.frame.DataFrame
          

          ? 第三個要學習的參數為join:拼接的方式,inner為交集,outer為并集,橫向拼接時由index的交/并集決定,縱向拼接時由columns的交/并集決定,同時,如果join=outer,匹配不上的地方以nan填充。

          <<< df1=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['A','B','C'],index=['a','b','c'])
          <<< df2=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['D','E','F'],index=['a','b','d'])
          # 將df1和df2進行橫向合并,取二者的并集
          <<< pd.concat([df1,df2],axis=1)
              A	B	C	D	E	F
          a	0	1	2	0	1	2
          b	3	4	5	3	4	5
          c	6	7	8	NaN	NaN	NaN
          d	NaN	NaN	NaN	6	7	8
          # 將df1和df2進行橫向合并,只取二者的交集
          <<< pd.concat([df1,df2],axis=1,join='inner')
              A	B	C	D	E	F
          a	0	1	2	0	1	2
          b	3	4	5	3	4	5
          

          ? 第四個要學習的參數為join_axes:以哪個數據對象的index/columns作為軸進行拼接,當進行橫向拼接時,join_axes為index的列表,如需根據df1對齊數據,則會保留df1的index,再將df2的數據進行拼接;同理,縱向拼接時為columns的列表。

          <<< df1=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['A','B','C'],index=['a','b','c'])
          <<< df2=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['D','E','F'],index=['a','b','d'])
          # 根據df1的index對齊數據
          <<< pd.concat([df1,df2],axis=1,join_axes=[df1.index])
              A	B	C	D	E	F
          a	0	1	2	0	1	2
          b	3	4	5	3	4	5
          c	6	7	8	NaN	NaN	NaN
          # 根據df2的index對齊數據
          <<< pd.concat([df1,df2],axis=1,join_axes=[df2.index])
              A	B	C	D	E	F
          a	0	1	2	0	1	2
          b	3	4	5	3	4	5
          d	NaN	NaN	NaN	6	7	8
          

          ? 第五個要學習的參數為ignore_index:默認為False,如果設置為true,則無視表原來的軸標簽,直接合并,合并后生成新的軸標簽。

          ? 這里需要注意的是,與append方法只能進行縱向拼接不同,concat方法既可以進行橫向拼接,也可以進行縱向拼接,若設置ignore_index=True,當進行橫向拼接時,則無視原表的columns,直接合并,合并后生成默認的columns;同理,當進行縱向拼接時,則是忽略原表的index,生成新的index。

          <<< df1=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['A','B','C'],index=['a','b','c'])
          <<< df2=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['D','E','F'],index=['a','b','d'])
          # 橫向拼接時,忽略的是columns,index仍起作用
          <<< pd.concat([df1,df2],axis=1,ignore_index=True)
              0	1	2	3	4	5
          a	0	1	2	0	1	2
          b	3	4	5	3	4	5
          c	6	7	8	NaN	NaN	NaN
          d	NaN	NaN	NaN	6	7	8
          # 縱向拼接時,忽略的是index,columns仍起作用
          pd.concat([df1,df2],axis=0,ignore_index=True)
              0	1	2	3	4	5
          a	0	1	2	0	1	2
          b	3	4	5	3	4	5
          c	6	7	8	NaN	NaN	NaN
          d	NaN	NaN	NaN	6	7	8
          

          ? 第六個要學習的參數為keys:表標識的列表,用來區分合并后的數據來源于哪個表,當ignore_index=True時,此參數的作用失效。

          <<< df1=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['A','B','C'],index=['a','b','c'])
          <<< df2=pd.DataFrame(np.arange(9).reshape(3,3),columns=   <<< ['D','E','F'],index=['a','b','d'])
          # 設置ignore_index=True時,參數keys不起作用
          <<< pd.concat([df1,df2],axis=1,ignore_index=True,keys=    <<< ['df1','df2'])
              0	1	2	3	4	5
          a	0	1	2	0	1	2
          b	3	4	5	3	4	5
          c	6	7	8	NaN	NaN	NaN
          d	NaN	NaN	NaN	6	7	8
          # 設置ignore_index=False,會根據keys的列表標識結果中的數據來源
          <<< pd.concat([df1,df2],axis=1,ignore_index=False,keys=   <<< ['df1','df2'])
              df1	        df2
              A	B	C	D	E	F
          a	0	1	2	0	1	2
          b	3	4	5	3	4	5
          c	6	7	8	NaN	NaN	NaN
          d	NaN	NaN	NaN	6	7	8
          

          總結:

          • append方法只能進行橫向拼接,且只支持對兩個對象進行拼接操作,但append支持單個對象的連接,此方法常用于循環中;
          • concat方法可用于橫向或縱向的拼接,同時可以設置以并集或交集的方式拼接

          如對append和concat方法還感興趣,建議可前往查看官方文檔:

          1)https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.append.html?highlight=append#pandas.DataFrame.append

          2)pandas.concat - pandas 0.21.0 documentation


          主站蜘蛛池模板: 成人在线一区二区| 国产激情一区二区三区成人91| 波多野结衣一区二区三区高清av | 制服丝袜一区二区三区| 成人一区二区三区视频在线观看| 久久青草精品一区二区三区| 91精品一区国产高清在线| 国产综合视频在线观看一区| 麻豆果冻传媒2021精品传媒一区下载 | 亚洲一区二区三区深夜天堂| 好爽毛片一区二区三区四| 国产一区在线播放| 国产一区二区三区影院| 中文字幕精品一区二区日本| 久久国产一区二区三区| 高清国产AV一区二区三区| 91久久精一区二区三区大全| 丝袜人妻一区二区三区| 亚洲国产专区一区| 国产伦精品一区二区免费| 国产亚洲综合精品一区二区三区 | 午夜无码视频一区二区三区| 国产精品综合一区二区三区| 春暖花开亚洲性无区一区二区| 亚洲欧美成人一区二区三区| 亚洲AV无码一区二区三区牲色| 欧美一区内射最近更新| 日本福利一区二区| 国产乱码精品一区二区三| 国产精华液一区二区区别大吗| 亚洲欧洲∨国产一区二区三区| 无码一区二区三区视频| 亚洲AV无码一区二区三区人| 天天视频一区二区三区| 无码人妻AⅤ一区二区三区水密桃| 国产亚洲一区二区三区在线不卡 | 精品乱码一区二区三区在线| 精品成人一区二区三区四区| 无码一区二区三区在线观看| 欧美一区内射最近更新| 亚洲男人的天堂一区二区|