整理 25 個 Pandas 實用技巧

來源:山陰少年 

顯示已安裝的版本

輸入下面的命令查詢 pandas 版本:

In [7]:pd.__version__
Out[7]: 0.24.2

如果你還想知道 pandas 所依賴的模塊的版本,你可以使用 show_versions() 函數:

In [9]:
pd.show_versions()

INSTALLED VERSIONS 
------------------ 
commit: None 
python: 3.7.3.final.0 
python-bits: 64 
OS: Darwin 
OS-release: 18.6.0 
machine: x86_64 
processor: i386 
byteorder: little 
LC_ALL: None 
LANG: en_US.UTF-8 
LOCALE: en_US.UTF-8 

pandas: 0.24.2 
pytest: None 
pip: 19.1.1 
setuptools: 41.0.1 
Cython: None 
numpy: 1.16.4 
scipy: None 
pyarrow: None 
xarray: None 
IPython: 7.5.0 
sphinx: None 
patsy: None 
dateutil: 2.8.0 
pytz: 2019.1 
blosc: None 
bottleneck: None 
tables: None 
numexpr: None 
feather: None 
matplotlib: 3.1.0 
openpyxl: None 
xlrd: None 
xlwt: None 
xlsxwriter: None 
lxml.etree: None 
bs4: None 
html5lib: None 
sqlalchemy: None 
pymysql: None 
psycopg2: None 
jinja2: 2.10.1 
s3fs: None 
fastparquet: None 
pandas_gbq: None 
pandas_datareader: None 
gcsfs: None

你可以查看到 Python,pandas, Numpy, matplotlib 等的版本信息。

創建示例 DataFrame

假設你需要創建一個示例 DataFrame。有很多種實現的途徑,我最喜歡的方式是傳一個字典給 DataFrame constructor,其中字典中的 keys 爲列名,values 爲列的取值。

現在如果你需要創建一個更大的 DataFrame,上述方法則需要太多的輸入。在這種情況下,你可以使用 Numpy 的 random.rand() 函數,告訴它行數和列數,將它傳遞給 DataFrame constructor:

這種方式很好,但如果你還想把列名變爲非數值型的,你可以強制地將一串字符賦值給 columns 參數

你可以想到,你傳遞的字符串的長度必須與列數相同。

更改列名

讓我們來看一下剛纔我們創建的示例 DataFrame:

我更喜歡在選取 pandas 列的時候使用點(.),但是這對那麼列名中含有空格的列不會生效。讓我們來修復這個問題。

更改列名最靈活的方式是使用 rename() 函數。你可以傳遞一個字典,其中 keys 爲原列名,values 爲新列名,還可以指定 axis:

In [14]:
df = df.rename({ col one : col_one ,  col two : col_two }axis= columns )

使用這個函數最好的方式是你需要更改任意數量的列名,不管是一列或者全部的列。

如果你需要一次性重新命令所有的列名,更簡單的方式就是重寫 DataFrame 的 columns 屬性

In [15]:
df.columns = [ col_one ,  col_two ]

如果你需要做的僅僅是將空格換成下劃線,那麼更好的辦法是使用 str.replace() 方法,這是因爲你都不需要輸入所有的列名:

In [16]:
df.columns = df.columns.str.replace(   ,  _ )

上述三個函數的結果都一樣,可以更改列名使得列名中不含有空格:

最後,如果你需要在列名中添加前綴或者後綴,你可以使用 add_prefix() 函數

或者使用 add_suffix() 函數

行序反轉

讓我們來看一下 drinks 這個 DataFame:

In [20]:
drinks.head()

Out[20]:

s3FPv3

該數據集描述了每個國家的平均酒消費量。如果你想要將行序反轉呢?

最直接的辦法是使用 loc 函數並傳遞::-1,跟 Python 中列表反轉時使用的切片符號一致:

In [21]:
drinks.loc[::-1].head()

Out[21]:

MAhkku

如果你還想重置索引使得它從 0 開始呢?

你可以使用 reset_index() 函數,告訴他去掉完全拋棄之前的索引

In [22]:
drinks.loc[::-1].reset_index(drop=True).head()

Out[22]:

4d9yL8

你可以看到,行序已經反轉,索引也被重置爲默認的整數序號。

列序反轉

跟之前的技巧一樣,你也可以使用 loc 函數將列從左至右反轉:

In [23]:
drinks.loc[:, ::-1].head()

Out[23]:

p4La0R

逗號之前的冒號表示選擇所有行,逗號之後的::-1 表示反轉所有的列,這就是爲什麼 country 這一列現在在最右邊。

通過數據類型選擇列

這裏有 drinks 這個 DataFrame 的數據類型:

In [24]:
drinks.dtypes

Out[24]:
country                          object
beer_servings                     int64
spirit_servings                   int64
wine_servings                     int64
total_litres_of_pure_alcohol    float64
continent                        object
dtype: object

假設你僅僅需要選取數值型的列,那麼你可以使用 select_dtypes() 函數

In [25]:
drinks.select_dtypes(include= number ).head()

Out[25]:

l5MQpW

這包含了 int 和 float 型的列。

你也可以使用這個函數來選取數據類型爲 object 的列:

你還可以選取多種數據類型,只需要傳遞一個列表即可:

你還可以用來排除特定的數據類型:

將字符型轉換爲數值型

讓我們來創建另一個示例 DataFrame:

這些數字實際上儲存爲字符型,導致其數據類型爲 object:

爲了對這些列進行數學運算,我們需要將數據類型轉換成數值型。你可以對前兩列使用 astype() 函數

但是,如果你對第三列也使用這個函數,將會引起錯誤,這是因爲這一列包含了破折號(用來表示 0)但是 pandas 並不知道如何處理它。

你可以對第三列使用 to_numeric() 函數,告訴其將任何無效數據轉換爲 NaN:

如果你知道 NaN 值代表 0,那麼你可以 fillna() 函數將他們替換成 0:

最後,你可以通過 apply() 函數一次性對整個 DataFrame 使用這個函數:

僅需一行代碼就完成了我們的目標,因爲現在所有的數據類型都轉換成 float:

減小 DataFrame 空間大小

pandas DataFrame 被設計成可以適應內存,所以有些時候你可以減小 DataFrame 的空間大小,讓它在你的系統上更好地運行起來。

這是 drinks 這個 DataFrame 所佔用的空間大小:

可以看到它使用了 30.4KB。

如果你對你的 DataFrame 有操作方面的問題,或者你不能將它讀進內存,那麼在讀取文件的過程中有兩個步驟可以使用來減小 DataFrame 的空間大小。

第一個步驟是隻讀取那些你實際上需要用到的列,可以調用 usecols 參數:

通過僅讀取用到的兩列,我們將 DataFrame 的空間大小縮小至 13.6KB。

第二步是將所有實際上爲類別變量的 object 列轉換成類別變量,可以調用 dtypes 參數:

通過將 continent 列讀取爲 category 數據類型,我們進一步地把 DataFrame 的空間大小縮小至 2.3KB。

值得注意的是,如果跟行數相比,category 數據類型的列數相對較小,那麼 catefory 數據類型可以減小內存佔用。

按行從多個文件中構建 DataFrame

假設你的數據集分化爲多個文件,但是你需要將這些數據集讀到一個 DataFrame 中。

舉例來說,我有一些關於股票的小數聚集,每個數據集爲單天的 CSV 文件。這是第一天的:

這是第二天的:

這是第三天的:

你可以將每個 CSV 文件讀取成 DataFrame,將它們結合起來,然後再刪除原來的 DataFrame,但是這樣會多佔用內存且需要許多代碼

更好的方式爲使用內置的 glob 模塊。你可以給 glob() 函數傳遞某種模式,包括未知字符,這樣它會返回符合該某事的文件列表。在這種方式下,glob 會查找所有以 stocks 開頭的 CSV 文件:

glob 會返回任意排序的文件名,這就是我們爲什麼要用 Python 內置的 sorted() 函數來對列表進行排序。

我們以生成器表達式用 read_csv() 函數來讀取每個文件,並將結果傳遞給 concat() 函數,這會將單個的 DataFrame 按行來組合:

不幸的是,索引值存在重複。爲了避免這種情況,我們需要告訴 concat() 函數來忽略索引,使用默認的整數索引:

按列從多個文件中構建 DataFrame

上一個技巧對於數據集中每個文件包含行記錄很有用。但是如果數據集中的每個文件包含的列信息呢?

這裏有一個例子,dinks 數據集被劃分成兩個 CSV 文件,每個文件包含三列:

同上一個技巧一樣,我們以使用 glob() 函數開始。這一次,我們需要告訴 concat() 函數按列來組合:

現在我們的 DataFrame 已經有六列了。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/T_VV4EIyhVmXQa6yB8m6Uw