整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Web數(shù)據(jù)提取:Python中BeautifulSoup與htmltab的結(jié)合使用

          . 引言

          Web數(shù)據(jù)提取,通常被稱為Web Scraping或Web Crawling,是指從網(wǎng)頁(yè)中自動(dòng)提取信息的過(guò)程。這項(xiàng)技術(shù)在市場(chǎng)研究、數(shù)據(jù)分析、信息聚合等多個(gè)領(lǐng)域都有廣泛的應(yīng)用。Python社區(qū)提供了豐富的工具和庫(kù)來(lái)支持這一技術(shù),其中BeautifulSoup和htmltab是兩個(gè)非常有用的庫(kù)。

          2. BeautifulSoup簡(jiǎn)介

          BeautifulSoup是一個(gè)用于解析HTML和XML文檔的Python庫(kù)。它能夠?qū)?fù)雜的HTML文檔轉(zhuǎn)換成易于使用的Python對(duì)象,從而可以方便地提取網(wǎng)頁(yè)中的各種數(shù)據(jù)。BeautifulSoup的主要特點(diǎn)包括:

          • 易于使用:提供了簡(jiǎn)單直觀的API來(lái)查找、修改和操作解析樹(shù)中的元素。
          • 強(qiáng)大的搜索功能:支持多種搜索方法,如通過(guò)標(biāo)簽名、類名、ID等快速定位元素。
          • 靈活的解析器支持:可以與Python標(biāo)準(zhǔn)庫(kù)中的HTML解析器或第三方解析器如lxml配合使用。

          3. htmltab庫(kù)介紹

          htmltab是一個(gè)專門(mén)用于從HTML中提取表格數(shù)據(jù)的Python庫(kù)。它提供了一種簡(jiǎn)單的方式來(lái)識(shí)別和解析網(wǎng)頁(yè)中的表格,并將它們轉(zhuǎn)換為Python的列表或Pandas的DataFrame。htmltab的主要特點(diǎn)包括:

          • 表格識(shí)別:能夠自動(dòng)識(shí)別網(wǎng)頁(yè)中的表格,并支持通過(guò)CSS選擇器進(jìn)行更精確的定位。
          • 數(shù)據(jù)轉(zhuǎn)換:支持將提取的表格數(shù)據(jù)轉(zhuǎn)換為多種格式,包括列表、字典和Pandas的DataFrame。
          • 易用性:提供了簡(jiǎn)潔的API,使得表格數(shù)據(jù)的提取變得簡(jiǎn)單直觀。

          4. BeautifulSoup與htmltab的結(jié)合使用

          結(jié)合使用BeautifulSoup和htmltab可以大大提高Web數(shù)據(jù)提取的效率和靈活性。以下是一個(gè)簡(jiǎn)單的示例,展示如何使用這兩個(gè)庫(kù)來(lái)提取Reddit子論壇中的表格數(shù)據(jù)。

          4.1 準(zhǔn)備工作

          首先,確保已經(jīng)安裝了所需的庫(kù)。如果尚未安裝,可以通過(guò)pip安裝:


          4.2 示例代碼

          5. 代碼解析

          在上述示例中,我們首先設(shè)置了代理服務(wù)器,這對(duì)于繞過(guò)某些網(wǎng)站的IP封鎖非常有用。然后,我們定義了一個(gè)函數(shù)get_reddit_content,它接受一個(gè)Reddit子論壇的名稱作為參數(shù),并返回該子論壇中的表格數(shù)據(jù)。 函數(shù)內(nèi)部,我們使用requests.Session來(lái)發(fā)送GET請(qǐng)求,并設(shè)置了代理。然后,使用BeautifulSoup解析HTML內(nèi)容,并利用htmltab庫(kù)來(lái)提取表格數(shù)據(jù)。最后,我們檢查響應(yīng)狀態(tài)碼,如果請(qǐng)求成功,就打印出表格數(shù)據(jù)。

          6. 結(jié)論

          通過(guò)結(jié)合使用BeautifulSoup和htmltab,我們可以高效地從Web頁(yè)面中提取所需的數(shù)據(jù)。這種方法不僅適用于Reddit,還可以擴(kuò)展到其他任何包含表格數(shù)據(jù)的網(wǎng)站。然而,需要注意的是,Web數(shù)據(jù)提取應(yīng)當(dāng)遵守目標(biāo)網(wǎng)站的robots.txt文件規(guī)定,尊重版權(quán)和隱私政策。

          者:George Seif

          編譯:ronghuaiyang

          導(dǎo)讀

          雖然Pandas的功能非常強(qiáng)大,但是對(duì)于大數(shù)據(jù)集來(lái)說(shuō),確實(shí)是很慢的。

          雖然 panda 是 Python 中用于數(shù)據(jù)處理的庫(kù),但它并不是真正為了速度而構(gòu)建的。了解一下新的庫(kù) Modin,Modin 是為了分布式 panda 的計(jì)算來(lái)加速你的數(shù)據(jù)準(zhǔn)備而開(kāi)發(fā)的。

          Pandas是處理 Python 數(shù)據(jù)的首選庫(kù)。它易于使用,并且在處理不同類型和大小的數(shù)據(jù)時(shí)非常靈活。它有大量的函數(shù),使得操縱數(shù)據(jù)變得輕而易舉。

          隨著時(shí)間的推移,各種Python包的流行程度

          但是有一個(gè)缺點(diǎn):對(duì)于較大的數(shù)據(jù)集來(lái)說(shuō),panda“慢”。

          默認(rèn)情況下,panda 使用單個(gè) CPU 內(nèi)核作為單個(gè)進(jìn)程執(zhí)行其函數(shù)。這對(duì)于較小的數(shù)據(jù)集工作得很好,因?yàn)槟憧赡懿粫?huì)注意到速度上的差異。但是,隨著數(shù)據(jù)集越來(lái)越大,計(jì)算量越來(lái)越大,如果只使用單個(gè) cpu 核,速度會(huì)受到很大的影響。它在數(shù)據(jù)集上同一時(shí)間只能計(jì)算一次,但該數(shù)據(jù)集可以有數(shù)百萬(wàn)甚至數(shù)十億行。

          然而,大多數(shù)用于數(shù)據(jù)科學(xué)的現(xiàn)代機(jī)器都有至少 2 個(gè) CPU 核。這意味著,以 2 個(gè) CPU 核為例,在使用 pandas 時(shí),50%或更多的計(jì)算機(jī)處理能力在默認(rèn)情況下不會(huì)執(zhí)行任何操作。當(dāng)你使用 4 核(現(xiàn)代 Intel i5)或 6 核(現(xiàn)代 Intel i7)時(shí),情況會(huì)變得更糟。pandas 的設(shè)計(jì)初衷并不是為了有效利用這種計(jì)算能力。

          Modin是一個(gè)新的庫(kù),通過(guò)在系統(tǒng)所有可用的 CPU 核上自動(dòng)分配計(jì)算來(lái)加速 pandas。有了它,對(duì)于任何尺寸的 pandas 數(shù)據(jù)數(shù)據(jù)集,Modin 聲稱能夠以 CPU 內(nèi)核的數(shù)量得到近乎線性的加速。

          讓我們看看它是如何工作的,并通過(guò)一些代碼示例進(jìn)行說(shuō)明。

          Modin 如何用 Pandas 并行計(jì)算

          給定 pandas 中的 DataFrame ,我們的目標(biāo)是以盡可能快的方式對(duì)其執(zhí)行某種計(jì)算或處理。可以用*.mean()取每一列的平均值,用groupby對(duì)數(shù)據(jù)進(jìn)行分組,用drop_duplicates()*刪除所有重復(fù)項(xiàng),或者使用其他任何內(nèi)置的 pandas 函數(shù)。

          在前一節(jié)中,我們提到了 pandas 如何只使用一個(gè) CPU 核進(jìn)行處理。自然,這是一個(gè)很大的瓶頸,特別是對(duì)于較大的 DataFrames,計(jì)算時(shí)就會(huì)表現(xiàn)出資源的缺乏。

          理論上,并行計(jì)算就像在每個(gè)可用的 CPU 核上的不同數(shù)據(jù)點(diǎn)上應(yīng)用計(jì)算一樣簡(jiǎn)單。對(duì)于一個(gè) pandas 的 DataFrame,一個(gè)基本的想法是將 DataFrame 分成幾個(gè)部分,每個(gè)部分的數(shù)量與你擁有的 CPU 內(nèi)核的數(shù)量一樣多,并讓每個(gè) CPU 核在一部分上運(yùn)行計(jì)算。最后,我們可以聚合結(jié)果,這是一個(gè)計(jì)算上很 cheap 的操作。

          多核系統(tǒng)如何更快地處理數(shù)據(jù)。對(duì)于單核進(jìn)程(左),所有10個(gè)任務(wù)都放在一個(gè)節(jié)點(diǎn)上。對(duì)于雙核進(jìn)程(右圖),每個(gè)節(jié)點(diǎn)承擔(dān)5個(gè)任務(wù),從而使處理速度加倍。

          這正是 Modin 所做的。它將 DataFrame 分割成不同的部分,這樣每個(gè)部分都可以發(fā)送到不同的 CPU 核。Modin 在行和列之間劃分 DataFrame。這使得 Modin 的并行處理可擴(kuò)展到任何形狀的 DataFrame。

          想象一下,如果給你一個(gè)列多行少的 DataFrame。有些庫(kù)只執(zhí)行跨行分區(qū),在這種情況下效率很低,因?yàn)槲覀兊牧斜刃卸唷5菍?duì)于 Modin 來(lái)說(shuō),由于分區(qū)是跨兩個(gè)維度進(jìn)行的,所以并行處理對(duì)于所有形狀的數(shù)據(jù)流都是有效的,不管它們是更寬的(很多列)、更長(zhǎng)的(很多行),還是兩者都有。

          panda的DataFrame(左)存儲(chǔ)為一個(gè)塊,只發(fā)送到一個(gè)CPU核。Modin的DataFrame(右)跨行和列進(jìn)行分區(qū),每個(gè)分區(qū)可以發(fā)送到不同的CPU核上,直到用光系統(tǒng)中的所有CPU核。

          上面的圖是一個(gè)簡(jiǎn)單的例子。Modin 實(shí)際上使用了一個(gè)“分區(qū)管理器”,它可以根據(jù)操作的類型改變分區(qū)的大小和形狀。例如,可能有一個(gè)操作需要整個(gè)行或整個(gè)列。在這種情況下,“分區(qū)管理器”將以它能找到的最優(yōu)方式執(zhí)行分區(qū)和分配到 CPU 核上。它是非常靈活的。

          為了在執(zhí)行并行處理時(shí)完成大量繁重的工作,Modin 可以使用 Dask 或 Ray。它們都是使用 Python api 的并行計(jì)算庫(kù),你可以選擇一個(gè)或另一個(gè)在運(yùn)行時(shí)與 Modin 一起使用。Ray 目前是最安全的一個(gè),因?yàn)樗€(wěn)定 —— Dask 后端是實(shí)驗(yàn)性的。

          已經(jīng)有足夠的理論了。讓我們來(lái)看看代碼和速度基準(zhǔn)測(cè)試!

          Modin 速度基準(zhǔn)測(cè)試

          安裝 Modin 的最簡(jiǎn)單的方法是通過(guò) pip。下面的命令安裝 Modin、Ray 和所有相關(guān)的依賴項(xiàng):

          pip install modin[ray]

          對(duì)于我們下面的例子和 benchmarks,我們使用了 Kaggle 的 CS:GO Competitive Matchmaking Data。CSV 的每一行都包含了 CS:GO 比賽中的一輪數(shù)據(jù)。

          現(xiàn)在,我們嘗試使用最大的 CSV 文件(有幾個(gè)),esea_master_dmg_demo .part1.csv,它有 1.2GB。有了這樣的體量,我們應(yīng)該能夠看到 pandas 有多慢,以及 Modin 是如何幫助我們加速的。對(duì)于測(cè)試,我使用一個(gè) i7-8700k CPU,它有 6 個(gè)物理內(nèi)核和 12 個(gè)線程。

          我們要做的第一個(gè)測(cè)試是使用 read_csv()讀取數(shù)據(jù)。Pandas 和 Modin 的代碼是完全一樣的。

          ### Read in the data with Pandas
          import pandas as pd
          
          s = time.time()
          df = pd.read_csv("esea_master_dmg_demos.part1.csv")
          e = time.time()
          print("Pandas Loading Time = {}".format(e-s))
          
          ### Read in the data with Modin
          import modin.pandas as pd
          
          s = time.time()
          df = pd.read_csv("esea_master_dmg_demos.part1.csv")
          e = time.time()
          print("Modin Loading Time = {}".format(e-s))

          為了測(cè)量速度,我導(dǎo)入了time模塊,并在read_csv()之前和之后放置了一個(gè)time()。panda 將數(shù)據(jù)從 CSV 加載到內(nèi)存需要 8.38 秒,而 Modin 需要 3.22 秒。這是 2.6 倍的加速。對(duì)于只修改 import 語(yǔ)句來(lái)說(shuō),這不算太寒酸!

          讓我們?cè)?DataFrame 上做一些更復(fù)雜的處理。連接多個(gè) DataFrames 是 panda 中的一個(gè)常見(jiàn)操作 — 我們可能有幾個(gè)或多個(gè)包含數(shù)據(jù)的 CSV 文件,然后必須一次讀取一個(gè)并連接它們。我們可以使用 panda 和 Modin 中的*pd.concat()*函數(shù)輕松做到這一點(diǎn)。

          我們希望 Modin 能夠很好地處理這種操作,因?yàn)樗幚泶罅康臄?shù)據(jù)。代碼如下所示。

          import pandas as pd
          df = pd.read_csv("esea_master_dmg_demos.part1.csv")
          
          s = time.time()
          df = pd.concat([df for _ in range(5)])
          e = time.time()
          print("Pandas Concat Time = {}".format(e-s))
          
          import modin.pandas as pd
          df = pd.read_csv("esea_master_dmg_demos.part1.csv")
          
          s = time.time()
          df = pd.concat([df for _ in range(5)])
          e = time.time()
          print("Modin Concat Time = {}".format(e-s))

          在上面的代碼中,我們將 DataFrame 與自身連接了 5 次。pandas 在 3.56 秒內(nèi)完成了連接操作,而 Modin 在 0.041 秒內(nèi)完成,速度提高了 86.83 倍!看起來(lái),即使我們只有 6 個(gè) CPU 核心,DataFrame 的分區(qū)也有助于提高速度。

          用于 DataFrame 清洗的 panda 函數(shù)是*.fillna()*函數(shù)。此函數(shù)查找 DataFrame 中的所有 NaN 值,并將它們替換為你選擇的值。panda 必須遍歷每一行和每一列來(lái)查找 NaN 值并替換它們。這是一個(gè)應(yīng)用 Modin 的絕佳機(jī)會(huì),因?yàn)槲覀円啻沃貜?fù)一個(gè)非常簡(jiǎn)單的操作。

          import pandas as pd
          df = pd.read_csv("esea_master_dmg_demos.part1.csv")
          
          s = time.time()
          df = df.fillna(value=0)
          e = time.time()
          print("Pandas Concat Time = {}".format(e-s))
          
          import modin.pandas as pd
          df = pd.read_csv("esea_master_dmg_demos.part1.csv")
          
          s = time.time()
          df = df.fillna(value=0)
          e = time.time()
          print("Modin Concat Time = {}".format(e-s))

          這次,Pandas 運(yùn)行*.fillna()*用了 1.8 秒,而 Modin 用了 0.21 秒,8.57 倍的加速!

          警告!

          Modin 總是這么快嗎?

          并不是這樣。

          在有些情況下,panda 實(shí)際上比 Modin 更快,即使在這個(gè)有 5,992,097(近 600 萬(wàn))行的大數(shù)據(jù)集上也是如此。下表顯示了我進(jìn)行的一些實(shí)驗(yàn)中 panda 與 Modin 的運(yùn)行時(shí)間。

          正如你所看到的,在某些操作中,Modin 要快得多,通常是讀取數(shù)據(jù)并查找值。其他操作,如執(zhí)行統(tǒng)計(jì)計(jì)算,在 pandas 中要快得多。

          使用 Modin 的實(shí)用技巧

          Modin 仍然是一個(gè)相當(dāng)新的庫(kù),并在不斷地發(fā)展和擴(kuò)大。因此,并不是所有的 pandas 功能都被完全加速了。如果你在 Modin 中嘗試使用一個(gè)還沒(méi)有被加速的函數(shù),它將默認(rèn)為 panda,因此不會(huì)有任何代碼錯(cuò)誤或錯(cuò)誤。

          默認(rèn)情況下,Modin 將使用計(jì)算機(jī)上所有可用的 CPU 內(nèi)核。在某些情況下,你可能希望限制 Modin 可以使用的 CPU 內(nèi)核的數(shù)量,特別是如果你希望在其他地方使用這種計(jì)算能力。我們可以通過(guò) Ray 中的初始化設(shè)置來(lái)限制 Modin 可以訪問(wèn)的 CPU 內(nèi)核的數(shù)量,因?yàn)?Modin 在后端使用它。

          import ray
          ray.init(num_cpus=4)
          import modin.pandas as pd

          在處理大數(shù)據(jù)時(shí),數(shù)據(jù)集的大小超過(guò)系統(tǒng)上的內(nèi)存(RAM)的情況并不少見(jiàn)。Modin 有一個(gè)特殊的標(biāo)志,我們可以設(shè)置為“true”,這將使其進(jìn)入“out of core”模式。這意味著 Modin 將使用你的磁盤(pán)作為你的內(nèi)存溢出存儲(chǔ),允許你處理比你的 RAM 大得多的數(shù)據(jù)集。我們可以設(shè)置以下環(huán)境變量來(lái)啟用此功能:

          export MODIN_OUT_OF_CORE=true

          總結(jié)

          這就是使用 Modin 加速 panda 函數(shù)的指南。只需修改 import 語(yǔ)句就可以很容易地做到這一點(diǎn)。希望你發(fā)現(xiàn) Modin 至少在一些情況下對(duì)加速 panda有用。

          英文原文:https://www.kdnuggets.com/2019/11/speed-up-pandas-4x.html

          讀:Pandas 是一個(gè)強(qiáng)大的分析結(jié)構(gòu)化數(shù)據(jù)的工具集,它的使用基礎(chǔ)是 Numpy(提供高性能的矩陣運(yùn)算),用于數(shù)據(jù)挖掘和數(shù)據(jù)分析,同時(shí)也提供數(shù)據(jù)清洗功能。

          本文收集了 Python 數(shù)據(jù)分析庫(kù) Pandas 及相關(guān)工具的日常使用方法,備查,持續(xù)更新中。

          作者:李慶輝

          來(lái)源:華章科技

          縮寫(xiě)說(shuō)明:

          • df:任意的 Pandas DataFrame 對(duì)象
          • s:任意的 Pandas Series 對(duì)象
          • 注:有些屬性方法 df 和 s 都可以使用

          推薦資源:

          • pandas 在線教程
          • https://www.gairuo.com/p/pandas-tutorial
          • 書(shū)籍 《深入淺出Pandas:利用Python進(jìn)行數(shù)據(jù)處理與分析》

          01 環(huán)境搭建

          # https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/
          # https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/
          # https://docs.conda.io/en/latest/miniconda.html
          # excel 處理相關(guān)包 xlrd / openpyxl / xlsxwriter
          # 解析網(wǎng)頁(yè)包 requests / lxml / html5lib / BeautifulSoup4
          # 計(jì)算包:scipy
          pip install jupyter pandas matplotlib
          # 國(guó)外網(wǎng)絡(luò)慢,可指定國(guó)內(nèi)源快速下載安裝
          pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple

          Conda 多 Python 版本環(huán)境:

          # 創(chuàng)建新環(huán)境,<環(huán)境名稱>, python 版本
          conda create -n py39 python=3.9
          # 刪除環(huán)境
          conda remove -n py39 --all
          # 進(jìn)入、激活環(huán)境
          conda activate py39
          # 退出環(huán)境
          conda deactivate
          # 查看所有虛擬環(huán)境及當(dāng)前環(huán)境
          conda info -e

          02 Jupyter Notebook 快捷鍵

          啟動(dòng) Jupyter Notebook:jupyter notebook

          快捷鍵及功能:

          • <tab>:代碼提示
          • Shift+ Enter:執(zhí)行本行并定位到新增的行
          • Shift+Tab(1-3次):查看函數(shù)方法說(shuō)明
          • D, D:雙擊 D 刪除本行
          • A / B:向上 / 下增加一行
          • M / Y:Markdown / 代碼模式

          03 導(dǎo)入庫(kù)包

          import pandas as pd # 最新為 1.4.1 版本 (2022-02-12)
          import numpy as np
          import matplotlib.pyplot as plt
          import seaborn as sns
          %matplotlib inline

          04 導(dǎo)入數(shù)據(jù)

          # 從 CSV 文件導(dǎo)入數(shù)據(jù)
          pd.read_csv('file.csv', name=['列名','列名2'])
          # 從限定分隔符的文本文件導(dǎo)入數(shù)據(jù)
          pd.read_table(filename, header=0)
          # Excel 導(dǎo)入,指定 sheet 和表頭
          pd.read_excel('file.xlsx', sheet_name=' 表1', header=0)
          # 從 SQL 表/庫(kù)導(dǎo)入數(shù)據(jù)
          pd.read_sql(query, connection_object)
          # 從 JSON 格式的字符串導(dǎo)入數(shù)據(jù)
          pd.read_json(json_string)
          # 解析 URL、字符串或者 HTML 文件,抽取其中的 tables 表格
          pd.read_html(url)
          # 從你的粘貼板獲取內(nèi)容,并傳給 read_table()
          pd.read_clipboard()
          # 從字典對(duì)象導(dǎo)入數(shù)據(jù),Key 是列名,Value是數(shù)據(jù)
          pd.DataFrame(dict)
          # 導(dǎo)入字符串
          from io import StringIO
          pd.read_csv(StringIO(web_data.text))

          05 導(dǎo)出輸出數(shù)據(jù)

          # 導(dǎo)出數(shù)據(jù)到CSV文件
          df.to_csv('filename.csv')
          # 導(dǎo)出數(shù)據(jù)到Excel文件
          df.to_excel('filename.xlsx', index=True)
          # 導(dǎo)出數(shù)據(jù)到 SQL 表
          df.to_sql(table_name, connection_object)
          # 以Json格式導(dǎo)出數(shù)據(jù)到文本文件
          df.to_json(filename)
          # 其他
          df.to_html() # 顯示 HTML 代碼
          df.to_markdown() # 顯示 markdown 代碼
          df.to_string() # 顯示格式化字符
          df.to_latex(index=False) # LaTeX tabular, longtable
          df.to_dict('split') # 字典, 格式 list/series/records/index
          df.to_clipboard(sep=',', index=False) # 存入系統(tǒng)剪貼板
          
          # 將兩個(gè)表格輸出到一個(gè)excel文件里面,導(dǎo)出到多個(gè) sheet
          writer=pd.ExcelWriter('new.xlsx')
          df_1.to_excel(writer,sheet_name='第一個(gè)', index=False)
          df_2.to_excel(writer,sheet_name='第二個(gè)', index=False)
          writer.save() # 必須運(yùn)行writer.save(),不然不能輸出到本地
          
          # 寫(xiě)法2
          with pd.ExcelWriter('new.xlsx') as writer:
          df1.to_excel(writer, sheet_name='第一個(gè)')
          df2.to_excel(writer, sheet_name='第二個(gè)')
          # 用 xlsxwriter 導(dǎo)出支持合并單元格、顏色、圖表等定制功能
          # https://xlsxwriter.readthedocs.io/working_with_pandas.html

          06 創(chuàng)建測(cè)試對(duì)象

          # 創(chuàng)建20行5列的隨機(jī)數(shù)組成的 DataFrame 對(duì)象
          pd.DataFrame(np.random.rand(20,5))
          # 從可迭代對(duì)象 my_list 創(chuàng)建一個(gè) Series 對(duì)象
          pd.Series(my_list)
          # 增加一個(gè)日期索引
          df.index = pd.date_range('1900/1/30', periods=df.shape[0])
          # 創(chuàng)建隨機(jī)數(shù)據(jù)集
          df = pd.util.testing.makeDataFrame()
          # 創(chuàng)建隨機(jī)日期索引數(shù)據(jù)集
          df = pd.util.testing.makePeriodFrame()
          df = pd.util.testing.makeTimeDataFrame()
          # 創(chuàng)建隨機(jī)混合類型數(shù)據(jù)集
          df = pd.util.testing.makeMixedDataFrame()

          07 查看、檢查、統(tǒng)計(jì)、屬性

          df.head(n) # 查看 DataFrame 對(duì)象的前n行
          df.tail(n) # 查看 DataFrame 對(duì)象的最后n行
          df.sample(n) # 查看 n 個(gè)樣本,隨機(jī)
          df.shape # 查看行數(shù)和列數(shù)
          df.info() # 查看索引、數(shù)據(jù)類型和內(nèi)存信息
          df.describe() # 查看數(shù)值型列的匯總統(tǒng)計(jì)
          df.dtypes # 查看各字段類型
          df.axes # 顯示數(shù)據(jù)行和列名
          df.mean() # 返回所有列的均值
          df.mean(1) # 返回所有行的均值,下同
          df.corr() # 返回列與列之間的相關(guān)系數(shù)
          df.count() # 返回每一列中的非空值的個(gè)數(shù)
          df.max() # 返回每一列的最大值
          df.min() # 返回每一列的最小值
          df.median() # 返回每一列的中位數(shù)
          df.std() # 返回每一列的標(biāo)準(zhǔn)差
          df.var() # 方差
          s.mode() # 眾數(shù)
          s.prod() # 連乘
          s.cumprod() # 累積連乘,累乘
          df.cumsum(axis=0) # 累積連加,累加
          s.nunique() # 去重?cái)?shù)量,不同值的量
          df.idxmax() # 每列最大的值的索引名
          df.idxmin() # 最小
          df.columns # 顯示所有列名
          df.team.unique() # 顯示列中的不重復(fù)值
          # 查看 Series 對(duì)象的唯一值和計(jì)數(shù), 計(jì)數(shù)占比: normalize=True
          s.value_counts(dropna=False)
          # 查看 DataFrame 對(duì)象中每一列的唯一值和計(jì)數(shù)
          df.apply(pd.Series.value_counts)
          df.duplicated() # 重復(fù)行
          df.drop_duplicates() # 刪除重復(fù)行
          # set_option、reset_option、describe_option 設(shè)置顯示要求
          pd.get_option()
          # 設(shè)置行列最大顯示數(shù)量,None 為不限制
          pd.options.display.max_rows = None
          pd.options.display.max_columns = None
          df.col.argmin() # 最大值[最小值 .argmax()] 所在位置的自動(dòng)索引
          df.col.idxmin() # 最大值[最小值 .idxmax()] 所在位置的定義索引
          # 累計(jì)統(tǒng)計(jì)
          ds.cumsum() # 前邊所有值之和
          ds.cumprod() # 前邊所有值之積
          ds.cummax() # 前邊所有值的最大值
          ds.cummin() # 前邊所有值的最小值
          # 窗口計(jì)算(滾動(dòng)計(jì)算)
          ds.rolling(x).sum() #依次計(jì)算相鄰x個(gè)元素的和
          ds.rolling(x).mean() #依次計(jì)算相鄰x個(gè)元素的算術(shù)平均
          ds.rolling(x).var() #依次計(jì)算相鄰x個(gè)元素的方差
          ds.rolling(x).std() #依次計(jì)算相鄰x個(gè)元素的標(biāo)準(zhǔn)差
          ds.rolling(x).min() #依次計(jì)算相鄰x個(gè)元素的最小值
          ds.rolling(x).max() #依次計(jì)算相鄰x個(gè)元素的最大值

          08 數(shù)據(jù)清理

          df.columns = ['a','b','c'] # 重命名列名
          df.columns = df.columns.str.replace(' ', '_') # 列名空格換下劃線
          df.loc[df.AAA >= 5, ['BBB', 'CCC']] = 555 # 替換數(shù)據(jù)
          df['pf'] = df.site_id.map({2: '小程序', 7:'M 站'}) # 將枚舉換成名稱
          pd.isnull() # 檢查DataFrame對(duì)象中的空值,并返回一個(gè) Boolean 數(shù)組
          pd.notnull() # 檢查DataFrame對(duì)象中的非空值,并返回一個(gè) Boolean 數(shù)組
          df.drop(['name'], axis=1) # 刪除列
          df.drop([0, 10], axis=0) # 刪除行
          del df['name'] # 刪除列
          df.dropna() # 刪除所有包含空值的行
          df.dropna(axis=1) # 刪除所有包含空值的列
          df.dropna(axis=1,thresh=n) # 刪除所有小于 n 個(gè)非空值的行
          df.fillna(x) # 用x替換DataFrame對(duì)象中所有的空值
          df.fillna(value={'prov':'未知'}) # 指定列的空值替換為指定內(nèi)容
          s.astype(float) # 將Series中的數(shù)據(jù)類型更改為 float 類型
          df.index.astype('datetime64[ns]') # 轉(zhuǎn)化為時(shí)間格式
          s.replace(1, 'one') # 用 ‘one’ 代替所有等于 1 的值
          s.replace([1, 3],['one','three']) # 用'one'代替 1,用 'three' 代替 3
          df.rename(columns=lambda x: x + 1) # 批量更改列名
          df.rename(columns={'old_name': 'new_name'}) # 選擇性更改列名
          df.set_index('column_one') # 更改索引列
          df.rename(index=lambda x: x + 1) # 批量重命名索引
          # 重新命名表頭名稱
          df.columns = ['UID', '當(dāng)前待打款金額', '認(rèn)證姓名']
          df['是否設(shè)置提現(xiàn)賬號(hào)'] = df['狀態(tài)'] # 復(fù)制一列
          df.loc[:, ::-1] # 列順序反轉(zhuǎn)
          df.loc[::-1] # 行順序反轉(zhuǎn), 下方為重新定義索引
          df.loc[::-1].reset_index(drop=True)

          09 數(shù)據(jù)處理:Filter、Sort

          # 保留小數(shù)位,四舍六入五成雙
          df.round(2) # 全部
          df.round({'A': 1, 'C': 2}) # 指定列
          df['Name'] = df.Name # 取列名的兩個(gè)方法
          df[df.index == 'Jude'] # 按索引查詢要用 .index
          df[df[col] > 0.5] # 選擇col列的值大于0.5的行
          # 多條件查詢
          df[(df['team'] == 'A') &
          ( df['Q1'] > 80) &
          df.utype.isin(['老客', '老訪客'])]
          # 篩選為空的內(nèi)容
          df[df.order.isnull()]
          # 類似 SQL where in
          df[df.team.isin('A','B')]
          df[(df.team=='B') & (df.Q1 == 17)]
          df[~(df['team'] == 'A') | ( df['Q1'] > 80)] # 非,或
          df[df.Name.str.contains('張')] # 包含字符
          df.sort_values(col1) # 按照列col1排序數(shù)據(jù),默認(rèn)升序排列
          df.col1.sort_values() # 同上, -> s
          df.sort_values(col2, ascending=False) # 按照列 col1 降序排列數(shù)據(jù)
          # 先按列col1升序排列,后按col2降序排列數(shù)據(jù)
          df.sort_values([col1,col2], ascending=[True,False])
          df2 = pd.get_dummies(df, prefix='t_') # 將枚舉的那些列帶枚舉轉(zhuǎn)到列上
          s.set_index().plot()
          # 多索引處理
          dd.set_index(['utype', 'site_id', 'p_day'], inplace=True)
          dd.sort_index(inplace=True) # 按索引排序
          dd.loc['新訪客', 2, '2019-06-22'].plot.barh() # loc 中按順序指定索引內(nèi)容
          # 前100行, 不能指定行,如:df[100]
          df[:100]
          # 只取指定行
          df1 = df.loc[0:, ['設(shè)計(jì)師ID', '姓名']]
          # 將ages平分成5個(gè)區(qū)間并指定 labels
          ages = np.array([1,5,10,40,36,12,58,62,77,89,100,18,20,25,30,32])
          pd.cut(ages, [0,5,20,30,50,100],
          labels=[u"嬰兒",u"青年",u"中年",u"壯年",u"老年"])
          
          daily_index.difference(df_work_day.index) # 取出差別
          # 格式化
          df.index.name # 索引的名稱 str
          df.columns.tolist()
          df.values.tolist()
          df.總?cè)丝?values.tolist()
          data.apply(np.mean) # 對(duì) DataFrame 中的每一列應(yīng)用函數(shù) np.mean
          data.apply(np.max,axis=1) # 對(duì) DataFrame 中的每一行應(yīng)用函數(shù) np.max
          df.insert(1, 'three', 12, allow_duplicates=False) # 插入列 (位置、列名、[值])
          df.pop('class') # 刪除列
          # 增加一行
          df.append(pd.DataFrame({'one':2,
          'two':3,
          'three': 4.4},
          index=['f']),
          sort=True)
          # 指定新列
          iris.assign(sepal_ratio=iris['SepalWidth'] / iris['SepalLength']).head()
          df.assign(rate=lambda df: df.orders/df.uv)
          # shift 函數(shù)是對(duì)數(shù)據(jù)進(jìn)行平移動(dòng)的操作
          df['增幅'] = df['國(guó)內(nèi)生產(chǎn)總值'] - df['國(guó)內(nèi)生產(chǎn)總值'].shift(-1)
          df.tshift(1) # 時(shí)間移動(dòng),按周期
          # 和上相同,diff 函數(shù)是用來(lái)將數(shù)據(jù)進(jìn)行移動(dòng)之后與原數(shù)據(jù)差
          # 異數(shù)據(jù),等于 df.shift()-df
          df['增幅'] = df['國(guó)內(nèi)生產(chǎn)總值'].diff(-1)
          # 留存數(shù)據(jù),因?yàn)樽畲笠话銥閿?shù)據(jù)池
          df.apply(lambda x: x/x.max(), axis=1)
          
          # 取 best 列中值為列名的值寫(xiě)到 name 行上
          df['value'] = df.lookup(df['name'], df['best'])
          
          s.where(s > 1, 10) # 滿足條件下數(shù)據(jù)替換(10,空為 NaN)
          s.mask(s > 0) # 留下滿足條件的,其他的默認(rèn)為 NaN
          # 所有值加 1 (加減乘除等)
          df + 1 / df.add(1)
          # 管道方法,鏈?zhǔn)秸{(diào)用函數(shù),f(df)=df.pipe(f)
          def gb(df, by):
          result = df.copy()
          result = result.groupby(by).sum()
          return result 
          # 調(diào)用
          df.pipe(gb, by='team')
          # 窗口計(jì)算 '2s' 為兩秒
          df.rolling(2).sum()
          # 在窗口結(jié)果基礎(chǔ)上的窗口計(jì)算
          df.expanding(2).sum()
          # 超出(大于、小于)的值替換成對(duì)應(yīng)值
          df.clip(-4, 6)
          # AB 兩列想加增加 C 列
          df['C'] = df.eval('A+B')
          # 和上相同效果
          df.eval('C = A + B', inplace=True)
          # 數(shù)列的變化百分比
          s.pct_change(periods=2)
          # 分位數(shù), 可實(shí)現(xiàn)時(shí)間的中間點(diǎn)
          df.quantile(.5)
          # 排名 average, min,max,first,dense, 默認(rèn) average
          s.rank()
          # 數(shù)據(jù)爆炸,將本列的類列表數(shù)據(jù)和其他列的數(shù)據(jù)展開(kāi)鋪開(kāi)
          df.explode('A')
          # 枚舉更新
          status = {0:'未執(zhí)行', 1:'執(zhí)行中', 2:'執(zhí)行完畢', 3:'執(zhí)行異常'}
          df['taskStatus'] = df['taskStatus'].apply(status.get)
          df.assign(金額=0) # 新增字段
          df.loc[('bar', 'two'), 'A'] # 多索引查詢
          df.query('i0 == "b" & i1 == "b"') # 多索引查詢方法 2
          # 取多索引中指定級(jí)別的所有不重復(fù)值
          df.index.get_level_values(2).unique()
          # 去掉為零小數(shù),12.00 -> 12
          df.astype('str').applymap(lambda x: x.replace('.00', ''))
          # 插入數(shù)據(jù),在第三列加入「兩倍」列
          df.insert(3, '兩倍', df['值']*2)
          # 枚舉轉(zhuǎn)換
          df['gender'] = df.gender.map({'male':'男', 'female':'女'})
          # 增加本行之和列
          df['Col_sum'] = df.apply(lambda x: x.sum(), axis=1)
          # 對(duì)指定行進(jìn)行加和
          col_list= list(df)[2:] # 取請(qǐng)假范圍日期
          df['總天數(shù)'] = df[col_list].sum(axis=1) # 計(jì)算總請(qǐng)假天數(shù)
          # 對(duì)列求和,匯總
          df.loc['col_sum'] = df.apply(lambda x: x.sum())
          # 按指定的列表順序顯示
          df.reindex(order_list)
          # 按指定的多列排序
          df.reindex(['col_1', 'col_5'], axis="columns")

          10 數(shù)據(jù)選取

          df[col] # 根據(jù)列名,并以Series的形式返回列
          df[[col1, col2]] # 以DataFrame形式返回多列
          df.loc[df['team'] == 'B',['name']] # 按條件查詢,只顯示name 列
          s.iloc[0] # 按位置選取數(shù)據(jù)
          s.loc['index_one'] # 按索引選取數(shù)據(jù)
          df.loc[0,'A':'B'] # A到 B 字段的第一行 
          df.loc[2018:1990, '第一產(chǎn)業(yè)增加值':'第三產(chǎn)業(yè)增加值']
          df.loc[0,['A','B']] # d.loc[位置切片, 字段]
          df.iloc[0,:] # 返回第一行, iloc 只能是數(shù)字
          df.iloc[0,0] # 返回第一列的第一個(gè)元素
          dc.query('site_id > 8 and utype=="老客"').head() # 可以 and or / & |
          # 迭代器及使用
          for idx,row in df.iterrows(): row['id']
          # 迭代器對(duì)每個(gè)元素進(jìn)行處理
          df.loc[i,'鏈接'] = f'http://www.gairuo.com/p/{slug}.html'
          for i in df.Name:print(i) # 迭代一個(gè)列
          # 按列迭代,[列名, 列中的數(shù)據(jù)序列 S(索引名 值)]
          for label, content in df.items():print(label, content)
          # 按行迭代,迭代出整行包括索引的類似列表的內(nèi)容,可row[2]取
          for row in df.itertuples():print(row)
          df.at[2018, '總?cè)丝?#39;] # 按行列索引名取一個(gè)指定的單個(gè)元素
          df.iat[1, 2] # 索引和列的編號(hào)取單個(gè)元素
          s.nlargest(5).nsmallest(2) # 最大和最小的前幾個(gè)值
          df.nlargest(3, ['population', 'GDP'])
          df.take([0, 3]) # 指定多個(gè)行列位置的內(nèi)容
          # 按行列截取掉部分內(nèi)容,支持日期索引標(biāo)簽
          ds.truncate(before=2, after=4)
          # 將 dataframe 轉(zhuǎn)成 series
          df.iloc[:,0]
          float(str(val).rstrip('%')) # 百分?jǐn)?shù)轉(zhuǎn)數(shù)字
          df.reset_index(inplace=True) # 取消索引

          11 數(shù)據(jù)處理 GroupBy 透視

          df.groupby(col) # 返回一個(gè)按列col進(jìn)行分組的Groupby對(duì)象
          df.groupby([col1,col2]) # 返回一個(gè)按多列進(jìn)行分組的Groupby對(duì)象
          df.groupby(col1)[col2] # 返回按列col1進(jìn)行分組后,列col2的均值
          # 創(chuàng)建一個(gè)按列col1進(jìn)行分組,并計(jì)算col2和col3的最大值的數(shù)據(jù)透視表
          df.pivot_table(index=col1,
          values=[col2,col3],
          aggfunc=max,
          as_index=False)
          # 同上
          df.pivot_table(index=['site_id', 'utype'],
          values=['uv_all', 'regist_num'],
          aggfunc=['max', 'mean'])
          df.groupby(col1).agg(np.mean) # 返回按列col1分組的所有列的均值
          # 按列將其他列轉(zhuǎn)行
          pd.melt(df, id_vars=["day"], var_name='city', value_name='temperature')
          # 交叉表是用于統(tǒng)計(jì)分組頻率的特殊透視表
          pd.crosstab(df.Nationality,df.Handedness)
          # groupby 后排序,分組 agg 內(nèi)的元素取固定個(gè)數(shù)
          (
          df[(df.p_day >= '20190101')]
          .groupby(['p_day', 'name'])
          .agg({'uv':sum})
          .sort_values(['p_day','uv'], ascending=[False, False])
          .groupby(level=0).head(5) # 每天取5個(gè)頁(yè)面
          .unstack()
          .plot()
          )
          # 合并查詢經(jīng)第一個(gè)看(max, min, last, size:數(shù)量)
          df.groupby('結(jié)算類型').first()
          # 合并明細(xì)并分組統(tǒng)計(jì)加總('max', `mean`, `median`,
          # `prod`, `sum`, `std`,`var`, 'nunique'),'nunique'為去重的列表
          df1 = df.groupby(by='設(shè)計(jì)師ID').agg({'結(jié)算金額':sum})
          df.groupby(by=df.pf).ip.nunique() # groupby distinct, 分組+去重?cái)?shù)
          df.groupby(by=df.pf).ip.value_counts() # groupby 分組+去重的值及數(shù)量
          df.groupby('name').agg(['sum', 'median', 'count'])

          12 數(shù)據(jù)合并

          # 合并拼接行
          # 將df2中的行添加到df1的尾部
          df1.append(df2)
          # 指定列合并成一個(gè)新表新列
          ndf = (df['提名1']
          .append(df['提名2'], ignore_index=True)
          .append(df['提名3'], ignore_index=True))
          ndf = pd.DataFrame(ndf, columns=(['姓名']))
          # 將df2中的列添加到df1的尾部
          df.concat([df1, df2], axis=1)
          
          # 合并文件的各行
          df1 = pd.read_csv('111.csv', sep='\t')
          df2 = pd.read_csv('222.csv', sep='\t')
          excel_list = [df1, df2]
          # result = pd.concat(excel_list).fillna('')[:].astype('str')
          result = pd.concat(excel_list)[]
          result.to_excel('333.xlsx', index=False)
          
          # 合并指定目錄下所有的 excel (csv) 文件
          import glob
          files = glob.glob("data/cs/*.xls")
          dflist = []
          for i in files:
          dflist.append(pd.read_excel(i, usecols=['ID', '時(shí)間', '名稱']))
          
          df = pd.concat(dflist)
          
          # 合并增加列
          # 對(duì)df1的列和df2的列執(zhí)行SQL形式的join
          df1.join(df2,on=col1,how='inner')
          # 用 key 合并兩個(gè)表
          df_all = pd.merge(df_sku, df_spu, 
          how='left',
          left_on=df_sku['product_id'],
          right_on=df_spu['p.product_id'])

          13 時(shí)間處理 時(shí)間序列

          # 時(shí)間索引
          df.index = pd.DatetimeIndex(df.index)
          # 時(shí)間只保留日期
          df['date'] = df['time'].dt.date
          # 將指定字段格式化為時(shí)間類型
          df["date"] = pd.to_datetime(df['時(shí)間'])
          # 轉(zhuǎn)化為北京時(shí)間
          df['time'] = df['time'].dt.tz_convert('Asia/Shanghai')
          # 轉(zhuǎn)為指定格式,可能會(huì)失去秒以后的精度
          df['time'] = df['time'].dt.strftime("%Y-%m-%d %H:%M:%S")
          dc.index = pd.to_datetime(dc.index, format='%Y%m%d', errors='ignore')
          # 時(shí)間,參與運(yùn)算
          pd.DateOffset(days=2)
          # 當(dāng)前時(shí)間
          pd.Timestamp.now()
          pd.to_datetime('today')
          # 判斷時(shí)間是否當(dāng)天
          pd.datetime.today().year == df.start_work.dt.year
          df.time.astype('datetime64[ns]').dt.date == pd.to_datetime('today')
          # 定義個(gè)天數(shù)
          import datetime
          days = lambda x: datetime.timedelta(days=x)
          days(2)
          # 同上,直接用 pd 包裝的
          pd.Timedelta(days=2)
          # unix 時(shí)間戳
          pd.to_datetime(ted.film_date, unit='ms')
          # 按月(YMDHminS)采集合計(jì)數(shù)據(jù)
          df.set_index('date').resample('M')['quantity'].sum()
          df.set_index('date').groupby('name')['ext price'].resample("M").sum()
          # 按天匯總,index 是 datetime 時(shí)間類型
          df.groupby(by=df.index.date).agg({'uu':'count'})
          # 按周匯總
          df.groupby(by=df.index.weekday).uu.count()
          # 按月進(jìn)行匯總
          df.groupby(['name', pd.Grouper(key='date', freq='M')])['ext price'].sum()
          # 按月進(jìn)行匯總
          df.groupby(pd.Grouper(key='day', freq='1M')).sum()
          # 按照年度,且截止到12月最后一天統(tǒng)計(jì) ext price 的 sum 值
          df.groupby(['name', pd.Grouper(key='date', freq='A-DEC')])['ext price'].sum()
          # 按月的平均重新采樣
          df['Close'].resample('M').mean()
          # https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases
          # 取時(shí)間范圍,并取工作日
          rng = pd.date_range(start="6/1/2016",end="6/30/2016",freq='B')
          # 重新定時(shí)數(shù)據(jù)頻度,按一定補(bǔ)充方法
          df.asfreq('D', method='pad')
          # 時(shí)區(qū),df.tz_convert('Europe/Berlin')
          df.time.tz_localize(tz='Asia/Shanghai')
          # 轉(zhuǎn)北京時(shí)間
          df['Time'] = df['Time'].dt.tz_localize('UTC').dt.tz_convert('Asia/Shanghai')
          # 查看所有時(shí)區(qū)
          from pytz import all_timezones
          print (all_timezones)
          # 時(shí)長(zhǎng),多久,兩個(gè)時(shí)間間隔時(shí)間,時(shí)差
          df['duration'] = pd.to_datetime(df['end']) - pd.to_datetime(df['begin'])
          # 指定時(shí)間進(jìn)行對(duì)比
          df.Time.astype('datetime64[ns]') < pd.to_datetime('2019-12-11 20:00:00', format='%Y-%m-%d %H:%M:%S')

          14 常用備忘

          # 解決科學(xué)計(jì)數(shù)法問(wèn)題
          df = pd.read_csv('111.csv', sep='\t').fillna('')[:].astype('str')
          # 和訂單量相關(guān)性最大到小顯示
          dd.corr().total_order_num.sort_values(ascending=False)
          
          # 解析列表、json 字符串
          import ast
          ast.literal_eval("[{'id': 7, 'name': 'Funny'}]")
          
          # Series apply method applies a function to
          # every element in a Series and returns a Series
          ted.ratings.apply(str_to_list).head()
          # lambda is a shorter alternative
          ted.ratings.apply(lambda x: ast.literal_eval(x))
          # an even shorter alternative is to apply the 
          # function directly (without lambda)
          ted.ratings.apply(ast.literal_eval)
          # 索引 index 使用 apply()
          df.index.to_series().apply()

          15 樣式顯示

          # https://pbpython.com/styling-pandas.html
          df['per_cost'] = df['per_cost'].map('{:,.2f}%'.format) # 顯示%比形式
          # 指定列表(值大于0)加背景色
          df.style.applymap(lambda x: 'background-color: grey' if x>0 else '',
          subset=pd.IndexSlice[:, ['B', 'C']])
          
          # 最大值最小值加背景色
          df.style.highlight_max(color='lightgreen').highlight_min(color='#cd4f39')
          df.style.format('{:.2%}', subset=pd.IndexSlice[:, ['B']]) # 顯示百分號(hào)
          
          # 指定各列的樣式
          format_dict = {'sum':'${0:,.0f}',
          'date': '{:%Y-%m}',
          'pct_of_total': '{:.2%}'
          'c': str.upper}
          
          # 一次性樣式設(shè)置
          (df.style.format(format_dict) # 多種樣式形式
          .hide_index()
          # 指定列按顏色深度表示值大小, cmap 為 matplotlib colormap
          .background_gradient(subset=['sum_num'], cmap='BuGn')
          # 表格內(nèi)作橫向 bar 代表值大小
          .bar(color='#FFA07A', vmin=100_000, subset=['sum'], align='zero')
          # 表格內(nèi)作橫向 bar 代表值大小
          .bar(color='lightgreen', vmin=0, subset=['pct_of_total'], align='zero')
          # 下降(小于0)為紅色, 上升為綠色
          .bar(color=['#ffe4e4','#bbf9ce'], vmin=0, vmax=1, subset=['增長(zhǎng)率'], align='zero')
          # 給樣式表格起個(gè)名字
          .set_caption('2018 Sales Performance')
          .hide_index())
          
          # 按條件給整行加背景色(樣式)
          def background_color(row):
          if row.pv_num >= 10000:
          return ['background-color: red'] * len(row)
          elif row.pv_num >= 100:
          return ['background-color: yellow'] * len(row)
          return [''] * len(row)
          # 使用
          df.style.apply(background_color, axis=1)

          16 表格中的直方圖,sparkline 圖形

          import sparklines
          import numpy as np
          def sparkline_str(x):
          bins=np.histogram(x)[0]
          sl = ''.join(sparklines.sparklines(bins))
          return sl
          sparkline_str.__name__ = "sparkline"
          # 畫(huà)出趨勢(shì)圖,保留兩位小數(shù)
          df.groupby('name')['quantity', 'ext price'].agg(['mean', sparkline_str]).round(2)
          
          # sparkline 圖形
          # https://hugoworld.wordpress.com/2019/01/26/sparklines-in-jupyter-notebooks-ipython-and-pandas/
          def sparkline(data, figsize=(4, 0.25), **kwargs):
          """
          creates a sparkline
          """
          
          # Turn off the max column width so the images won't be truncated
          pd.set_option('display.max_colwidth', -1)
          
          # Turning off the max column will display all the data
          # if gathering into sets / array we might want to restrict to a few items
          pd.set_option('display.max_seq_items', 3)
          
          #Monkey patch the dataframe so the sparklines are displayed
          pd.DataFrame._repr_html_ = lambda self: self.to_html(escape=False)
          
          from matplotlib import pyplot as plt
          import base64
          from io import BytesIO
          
          data = list(data)
          
          *_, ax = plt.subplots(1, 1, figsize=figsize, **kwargs)
          ax.plot(data)
          ax.fill_between(range(len(data)), data, len(data)*[min(data)], alpha=0.1)
          ax.set_axis_off()
          
          img = BytesIO()
          plt.savefig(img)
          plt.close()
          return '<img src="data:image/png;base64, {}" />'.format(base64.b64encode(img.getvalue()).decode())
          
          # 使用
          df.groupby('name')['quantity', 'ext price'].agg(['mean', sparkline])
          df.apply(sparkline, axis=1) # 僅支持橫向數(shù)據(jù)畫(huà)線,可做 T 轉(zhuǎn)置

          17 可視化

          kind : str

          • 'line' : line plot (default)
          • 'bar' : vertical bar plot
          • 'barh' : horizontal bar plot
          • 'hist' : histogram
          • 'box' : boxplot
          • 'kde' : Kernel Density Estimation plot
          • 'density' : same as 'kde'
          • 'area' : area plot
          • 'pie' : pie plot

          常用方法:

          df88.plot.bar(y='rate', figsize=(20, 10)) # 圖形大小,單位英寸
          df_1[df_1.p_day > '2019-06-01'].plot.bar(x='p_day', y=['total_order_num','order_user'], figsize=(16, 6)) # 柱狀圖
          # 每條線一個(gè)站點(diǎn),各站點(diǎn)的 home_remain, stack的意思是堆疊,堆積
          # unstack 即“不要堆疊”
          (df[(df.p_day >= '2019-05-1') & (df.utype == '老客')].groupby(['p_day', 'site_id'])['home_remain'].sum().unstack().plot.line())
          # 折線圖,多條, x 軸默認(rèn)為 index
          dd.plot.line(x='p_day', y=['uv_all', 'home_remain'])
          dd.loc['新訪客', 2].plot.scatter(x='order_user', y='paid_order_user') # 散點(diǎn)圖
          dd.plot.bar(color='blue') # 柱狀圖, barh 為橫向柱狀圖
          sns.heatmap(dd.corr()) # 相關(guān)性可視化
          # 刻度從0開(kāi)始,指定范圍 ylim=(0,100), x 軸相同
          s.plot.line(ylim=0)
          
          # 折線顏色 https://matplotlib.org/examples/color/named_colors.html
          # 樣式( '-','--','-.',':' )
          # 折線標(biāo)記 https://matplotlib.org/api/markers_api.html
          # grid=True 顯示刻度 etc: https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html
          s.plot.line(color='green', linestyle='-', marker='o')
          
          # 兩個(gè)圖繪在一起
          [df['數(shù)量'].plot.kde(), df['數(shù)量'].plot.hist()]
          
          # 對(duì)表中的數(shù)據(jù)按顏色可視化
          import seaborn as sns
          cm = sns.light_palette("green", as_cmap=True)
          df.style.background_gradient(cmap=cm, axis=1)
          
          # 將數(shù)據(jù)轉(zhuǎn)化為二維數(shù)組
          [i for i in zip([i.strftime('%Y-%m-%d') for i in s.index.to_list()], s.to_list())]
          
          # 和 plot 用法一樣 https://hvplot.pyviz.org/user_guide/Plotting.html
          import hvplot.pandas
          
          # 打印 Sqlite 建表語(yǔ)句
          print(pd.io.sql.get_schema(fdf, 'table_name'))

          18 Jupyter notebooks 問(wèn)題

          # jupyter notebooks plt 圖表配置
          import matplotlib.pyplot as plt
          plt.rcParams['figure.figsize'] = (15.0, 8.0) # 固定顯示大小
          plt.rcParams['font.family'] = ['sans-serif'] # 顯示中文問(wèn)題
          plt.rcParams['font.sans-serif'] = ['SimHei'] # 顯示中文問(wèn)題
          
          # 輸出單行全部變量
          from IPython.core.interactiveshell import InteractiveShell
          InteractiveShell.ast_node_interactivity = 'all'
          
          # jupyter notebooks 頁(yè)面自適應(yīng)寬度
          from IPython.core.display import display, HTML
          display(HTML("<style>.container { width:100% !important; }</style>"))
          # 背景白色 <style>#notebook_panel {background: #ffffff;}</style>
          
          # jupyter notebooks 嵌入頁(yè)面內(nèi)容
          from IPython.display import IFrame
          IFrame('https://arxiv.org/pdf/1406.2661.pdf', width=800, height=450)
          
          # Markdown 一個(gè) cell 不支持多張粘貼圖片
          # 一個(gè)文件打印打開(kāi)只顯示一張圖片問(wèn)題解決
          # /site-packages/notebook/static/notebook/js/main.min.js var key 處
          # 33502、33504 行
          key = utils.uuid().slice(2,6)+encodeURIandParens(blob.name);
          key = utils.uuid().slice(2,6)+Object.keys(that.attachments).length;
          # https://github.com/ihnorton/notebook/commit/55687c2dc08817da587977cb6f19f8cc0103bab1
          
          # 多行輸出
          from IPython.core.interactiveshell import InteractiveShell
          InteractiveShell.ast_node_interactivity = 'all' #默認(rèn)為'last'
          
          # 執(zhí)行 shell 命令: ! <命令語(yǔ)句>
          
          # 在線可視化工具
          https://plot.ly/create

          19 Slideshow 幻燈片

          安裝 RISE 庫(kù):pip install RISE

          • [Alt+r] 播放/退出播放
          • 「,」逗號(hào)隱藏左側(cè)兩個(gè)大操作按鈕,「t」總覽 ppt,「/」黑屏
          • Slide:主頁(yè)面,通過(guò)按左右方向鍵進(jìn)行切換。
          • Sub-Slide:副頁(yè)面,通過(guò)按上下方向鍵進(jìn)行切換。全屏
          • Fragment:一開(kāi)始是隱藏的,按空格鍵或方向鍵后顯示,實(shí)現(xiàn)動(dòng)態(tài)效果。在一個(gè)頁(yè)面
          • Skip:在幻燈片中不顯示的單元。
          • Notes:作為演講者的備忘筆記,也不在幻燈片中顯示。

          關(guān)于作者:李慶輝,數(shù)據(jù)產(chǎn)品專家,某電商公司數(shù)據(jù)產(chǎn)品團(tuán)隊(duì)負(fù)責(zé)人,擅長(zhǎng)通過(guò)數(shù)據(jù)治理、數(shù)據(jù)分析、數(shù)據(jù)化運(yùn)營(yíng)提升公司的數(shù)據(jù)應(yīng)用水平。

          精通Python數(shù)據(jù)科學(xué)及Python Web開(kāi)發(fā),曾獨(dú)立開(kāi)發(fā)公司的自動(dòng)化數(shù)據(jù)分析平臺(tái),參與教育部“1+X”數(shù)據(jù)分析(Python)職業(yè)技能等級(jí)標(biāo)準(zhǔn)評(píng)審。

          中國(guó)人工智能學(xué)會(huì)會(huì)員,企業(yè)數(shù)字化、數(shù)據(jù)產(chǎn)品和數(shù)據(jù)分析講師,在個(gè)人網(wǎng)站“蓋若”上編寫(xiě)的技術(shù)和產(chǎn)品教程廣受歡迎。

          延伸閱讀

          《深入淺出Pandas》

          推薦語(yǔ):這是一本全面覆蓋了Pandas使用者的普遍需求和痛點(diǎn)的著作,基于實(shí)用、易學(xué)的原則,從功能、使用、原理等多個(gè)維度對(duì)Pandas做了全方位的詳細(xì)講解,既是初學(xué)者系統(tǒng)學(xué)習(xí)Pandas難得的入門(mén)書(shū),又是有經(jīng)驗(yàn)的Python工程師案頭必不可少的查詢手冊(cè)。


          主站蜘蛛池模板: 国产在线视频一区二区三区| 天堂Av无码Av一区二区三区| 一区二区三区高清| 欧美人妻一区黄a片| 成人无码一区二区三区| 91在线看片一区国产| 一区二区三区无码高清视频| 精品国产一区二区三区色欲 | 国产主播福利精品一区二区 | 99热门精品一区二区三区无码| 日韩AV片无码一区二区不卡| 中文字幕视频一区| 手机看片一区二区| 亚洲国产精品第一区二区三区| 成人一区二区三区视频在线观看| 国产成人无码精品一区二区三区| 国产福利电影一区二区三区| 日本一区二区三区日本免费| 无码中文字幕人妻在线一区二区三区 | 无码国产伦一区二区三区视频 | 成人无码一区二区三区| 无码毛片一区二区三区中文字幕 | 全国精品一区二区在线观看| 亚洲av永久无码一区二区三区| 91在线一区二区| 中文字幕日韩一区二区三区不卡| 久久一区二区明星换脸| 国偷自产av一区二区三区| 中文日韩字幕一区在线观看| 狠狠色婷婷久久一区二区三区| 国产另类ts人妖一区二区三区| 日本人真淫视频一区二区三区| 国产免费私拍一区二区三区| 成人在线观看一区| 国产成人精品一区二区三在线观看| 爆乳无码AV一区二区三区 | 亚洲高清一区二区三区| 在线成人一区二区| 日本一区二区三区免费高清| 午夜视频在线观看一区| 在线日韩麻豆一区|