10個高效的pandas技巧


10個高效的pandas技巧


原題 | 10 Python Pandas tricks that make your work more efficient

作者 | Shiu-Tang Li

原文 | https://towardsdatascience.com/10-python-pandas-tricks-that-make-your-work-more-efficient-2e8e483808ba

譯者 | kbsc13

聲明 | 翻譯是出於交流學習的目的,歡迎轉載,但請保留本文出於,請勿用作商業或者非法用途

導讀

Pandas 是一個廣泛應用於數據分析等領域的 Python 庫。關於它的教程有很多,但這裡會一些比較冷門但是非常有用的技巧。

read_csv

這是一個大家都應該知道的函數,因為它就是讀取 csv 文件的方法。

但如果需要讀取數據量很大的時候,可以添加一個參數--nrows=5,來先加載少量數據,這可以避免使用錯誤的分隔符,因為並不是所有的都採用逗號分隔,然後再加載整個數據集。

Ps. 在 Linux 的終端,可以採用 head 命令來查看文件的前 5 行數據,命令示例如下所示:

head -n 5 data.txt

加載數據後,可以通過方法df.columns.tolist()獲取所有的列名字,再採用參數usecols=['c1','c2',...] 來讀取真正需要的列。如果想讀取速度更快並且知道一些列的數據類型,可以使用參數 dtype={'c1':str, 'c2':int,...},使用這個參數的另一個好處是對於包含不同類型的列,比如同時包含字符串和整型的列,這個參數可以指定該列就是字符串或者整型的類型,避免在採用該列作為鍵進行融合不同表的時候出現錯誤。

Select_dtypes

如果必須用 Python 進行數據預處理,採用這個方法可以節省一些時間。在讀取表後,默認數據類型可以能是 bool, int64, float64, object, category, timedelta64, datetime64,首先可以用下面的方法來查看分佈情況和知道 dataframe 中包含哪些數據類型:

df.dtypes.value_counts()

接著使用下面的方法來選擇特定類型的數據,比如說數字特徵:

df.select_dtypes(include=['float64', 'int64'])

copy

這個方法很重要,首先先看看下面這個例子:

import pandas as pd
df1 = pd.DataFrame({ 'a':[0,0,0], 'b': [1,1,1]})
df2 = df1
df2['a'] = df2['a'] + 1
df1.head()

運行上述代碼後,會發現df1 的數值被改變了,這是因為 df2=df1 這段代碼並不是對 df1 進行拷貝,然後賦給 df2,而是設置了一個指向 df1 的指針。 因此任何對 df2 的改變都會改變 df1,如果要修改這個問題,可以採用下面的代碼:

df2 = df1.copy()

或者

from copy import deepcopy
df2 = deepcopy(df1)

map

這是一個非常酷的命令,可以用於做簡單的數據轉化操作。首先需要定義一個字典,它的鍵是舊數值,而其值是新的數值,如下所示:

level_map = {1: 'high', 2: 'medium', 3: 'low'}
df['c_level'] = df['c'].map(level_map)

還有一些例子:

  • 布爾值的 True,False 轉化為 1,0
  • 定義層次
  • 用戶定義的詞典編碼

apply or not apply

如果我們想創建一個新的採用其他列作為輸入的列,apply 方法是一個非常有用的方法:

def rule(x, y):
if x == 'high' and y > 10:
return 1
else:
return 0
df = pd.DataFrame({ 'c1':[ 'high' ,'high', 'low', 'low'], 'c2': [0, 23, 17, 4]})
df['new'] = df.apply(lambda x: rule(x['c1'], x['c2']), axis = 1)
df.head()

上面這段代碼我們先定義了一個兩個輸入參數的方法,然後採用apply 方法將其應用到 df 的兩列 c1, c2。

apply 的問題是有時候速度太慢了。如果是希望計算 c1 和 c2 兩列的最大值,可以這麼寫:

df['maximum'] = df.apply(lambda x: max(x['c1'], x['c2']), axis = 1)

但你會發現比下面這段代碼要慢很多:

df['maximum'] = df[['c1','c2']].max(axis=1)

要點:如果可以採用其他內置函數實現的工作,就不要採用apply 方法啦。比如,想對列c 的數值進行取捨為整數值,可以採用方法 round(df['c'], o) 或者 df['c'].round(o),而不是使用apply 方法的代碼:df.apply(lambda x: round(x['c'], 0), axis=1)

value_counts

這個方法用於檢查數值的分佈情況。比如,你想知道c列的每個唯一數值出現的頻繁次數和可能的數值,可以如下所示:

df['c'].value_counts()

這裡還有一些有趣的技巧或者參數:

  1. normalize=True:如果想看頻率而不是次數,可以使用這個參數設置;
  2. dropna=False:查看包含缺失值的統計
  3. df['c'].value_counts().reset_index():如果想對這個統計轉換為一個 dataframe 並對其進行操作
  4. df['c'].value_counts().reset_index().sort_values(by='index') 或者是 df['c'].value_counts().sort_index() : 實現根據列的每個取值對統計表進行排序

number of missing values

當構建模型的時候,我們希望可以刪除掉帶有太多缺失值的行,或者都是缺失值的行。這可以通過採用.isnull() 和 .sum() 來計算特定列的缺失值數量:

import pandas as pd
import numpy as np
df = pd.DataFrame({ 'id': [1,2,3], 'c1':[0,0,np.nan], 'c2': [np.nan,1,1]})
df = df[['id', 'c1', 'c2']]
df['num_nulls'] = df[['c1', 'c2']].isnull().sum(axis=1)
df.head()

select rows with specific IDs

在 SQL 中這個操作可以通過SELECT * FROM … WHERE ID in (‘A001’, ‘C022’, …)來獲取特定 IDs 的記錄。而在 pandas 中,可以如下所示:

df_filter = df['ID'].isin(['A001','C022',...])
df[df_filter]

Percentile groups

假設有一個都是數值類型的列,然後希望對這些數值劃分成幾個組,比如前 5% 是第一組,5-20%是第二組,20%-50%是第三組,最後的50%是第四組。這可以採用.cut 方法,但這有另外一個選擇:

import numpy as np
cut_points = [np.percentile(df['c'], i) for i in [50, 80, 95]]
df['group'] = 1
for i in range(3):
df['group'] = df['group'] + (df['c'] < cut_points[i])
# or <= cut_points[i]

這個方法的速度非常快。

to_csv

最後是一個非常常用的方法,保存為 csv 文件。這裡也有兩個小技巧:

第一個就是print(df[:5].to_csv()),這段代碼可以打印前5行,並且也是會保存到文件的數據。

另一個技巧是處理混合了整數和缺失值的情況。當某一列同時有缺失值和整數,其數據類型是 float 類型而不是 int 類型。所以在導出該表的時候,可以添加參數float_format='%.of' 來將 float 類型轉換為整數。如果只是想得到整數,那麼可以去掉這段代碼中的 .o



分享到:


相關文章: