Pandas中的19種基礎(chǔ)編程方法

在品味了Pandas數(shù)據(jù)分析庫一段時(shí)間后,我已經(jīng)總結(jié)了很長一個(gè)有用的代碼段的列表,我發(fā)現(xiàn)我會(huì)一次又一次頻繁使用這些代碼段。這些小建議可以節(jié)省很多用來瀏覽Pandas文檔的時(shí)間。
在本文中,我們從將披薩餅訂單數(shù)據(jù)填充dataframe開始。如果你是新接觸Pandas,這里給出一些關(guān)鍵的詞。

Dataframe 數(shù)據(jù)中添加了索引的行和列,類似電子表格或者數(shù)據(jù)庫的表。
Series= 數(shù)據(jù)的單獨(dú)一列
Axis:0==行,1==列
Shape:Dataframe中(行數(shù),列數(shù))

  1. 導(dǎo)入CSV文件
    對(duì)于read_csv函數(shù)有一千種選項(xiàng)可以用來簡(jiǎn)化數(shù)據(jù)的前處理。沒有人想在清洗數(shù)據(jù)上花太多的時(shí)間,所以關(guān)鍵就在于你是否能在導(dǎo)入初始文件的時(shí)候就把事情搞定。
df = pd.read_csv('pizza.csv')

需要解析日期?僅僅需要把處理方法傳遞個(gè)相應(yīng)的列名。

df = pd.read_csv('pizza.csv', parse_dates=['dates'])

只需要某些列?

df = pd.read_csv('pizza.csv', usecols=['foo', 'bar'])
  1. 在Dataframe中探索數(shù)據(jù)
    你想要做的第一件事可能就是數(shù)據(jù)是什么樣的。這里有幾種方法可以檢查Pandas的數(shù)據(jù)。
  df.head()         #先頭5行
  df.tail()         #最后5行
  df.sample(5)      #行的隨機(jī)采樣
  df.shape          #一個(gè)元組,包含行列數(shù)目
  df.describe()     #
  df.info()         #內(nèi)存使用情況和數(shù)據(jù)類型
order_number date size topping price discount coupon
0 PZZA0001 08/21/16 Small Anchovies 12.99 3.5 Yes
1 PZZA0000 09/26/16 Large Pepperoni 14.50 0.0 No
2 PZZA0001 09/27/16 Extra Large Bell Pepper 19.99 0.0 No
3 PZZA0002 09/28/16 Extra Large Olives 20.99 5.0 Yes
4 PZZA0003 09/29/16 Extra Large Pepperoni 21.99 0.0 No

披薩餅數(shù)據(jù)的Dataframe的頭幾行結(jié)果如下:

order_number date size topping price discount coupon
0 PZZA0001 08/21/16 Small Anchovies 12.99 3.5 Yes
1 PZZA0000 09/26/16 Large Pepperoni 14.50 0.0 No
2 PZZA0001 09/27/16 Extra Large Bell Pepper 19.99 0.0 No
3 PZZA0002 09/28/16 Extra Large Olives 20.99 5.0 Yes
4 PZZA0003 09/29/16 Extra Large Pepperoni 21.99 0.0 No
  1. 在Dataframe中增加一個(gè)新列
    簡(jiǎn)單高效的做法就是在Dataframe中定義一個(gè)新列。下面的代碼給我們一個(gè)新列,其中每一行的值都設(shè)為23。通常你需要用一個(gè)數(shù)組或者Series來設(shè)定列的內(nèi)容,這里數(shù)組或者Series的長度必須跟數(shù)據(jù)中的行數(shù)相匹配。
df['new_column'] = 23

需要基于其他列來生產(chǎn)一個(gè)新列?

full_price = (df.price + df.discount)
df['original_price'] = full_price

需要根據(jù)某種順序來生成列?insert方法中第一個(gè)參數(shù)是列的位置。下面的代碼將列放到Dataframe的開始位置。

df.insert(0, 'original_price', full_price)
  1. 選擇一個(gè)具體單元格的值
    所謂的單元格這里指位置的是行列交叉所在的數(shù)據(jù),跟Excel里的單元格是一個(gè)意思。你可能感覺這比較簡(jiǎn)單,但是具體語法卻并不是那么直觀。在Pandas中有3個(gè)方法同時(shí)能做到這件事:.loc, .iloc, .ix——對(duì)新接觸的人而言,這又更加了理解的難度。

通常我都是用.ix,因?yàn)檫@個(gè)方法允許整數(shù)和字符串混合使用。首先輸入行的索引,然后是列的索引。

df.ix[2, 'topping']

你也可以通過點(diǎn)符號(hào)先選擇列,然后給定行的索引,這樣看起來更清爽:

df.topping.ix[2]

上述的兩種方法都會(huì)返回單元格的值:

>>> 'Bell Pepper'
  1. 通過條件邏輯來篩選DataFrame
    假設(shè)我們需要分析在topping列中包含菠蘿的訂單。
filtered_data = df[df.topping == 'pineapple']

或者我們要找的是高于一定價(jià)格線的訂單:

filtered_data = df[df.price > 11.99 ]

如果要同時(shí)滿足上述兩個(gè)條件我們?cè)趺崔k?僅僅將條件包裹成元組并將條件用位運(yùn)算符連接起來就行。

filtered_data = df[(df.price > 11.99) & (df.topping == 'Pineapple')]

現(xiàn)在我們得到了包含菠蘿并且topping價(jià)格超過11.99的所有訂單。

order_number date size topping price discount coupon
6 PZZA0006 10/01/16 Medium Pineapple 17.50 0.0 No
9 PZZA0009 10/04/16 Medium Pineapple 12.99 2.0 Yes
  1. 通過某一列來對(duì)DataFrame進(jìn)行排序
    下面的代碼意義不言自明,非常有用。
df.sort_values('price', axis=0, ascending=False)
  1. 對(duì)于列中的每行都應(yīng)用一個(gè)函數(shù)
    Python中匿名lambda函數(shù)非常適合這樣的任務(wù)。假設(shè)我們需要用一個(gè)自定義的函數(shù)來計(jì)算DataFrame中每一行的稅金。Pandas中的apply函數(shù)運(yùn)行我們將函數(shù)傳遞進(jìn)來,在列中的每一個(gè)值上使用。在這個(gè)例子中,我們通過在價(jià)格數(shù)據(jù)上執(zhí)行一個(gè)自定義的函數(shù)來抽取出新的稅金特征。
def calculate_taxes(price):
    taxes = price * 0.12
    return taxes

df['taxes'] = df.price.apply(calculate_taxes)
order_number price taxes
0 PZZA0000 12.99 1.5588
1 PZZA0001 14.50 1.7400
2 PZZA0002 19.99 2.3988
3 PZZA0003 20.99 2.5188
4 PZZA0004 21.99 2.6388
  1. 通過條件邏輯追加一個(gè)新列
    numpy中的where函數(shù)在根據(jù)條件邏輯來抽取特征方面非常有用。讓我們?cè)O(shè)想一下披薩店只有在銷售額度超過15美元時(shí)才有利潤。我們根據(jù)這個(gè)觀點(diǎn)創(chuàng)建一個(gè)新的列:
df['profitable'] = np.where(df['price']>=15.00, True, False)
  1. 找出復(fù)數(shù)列或者行的均值或者標(biāo)準(zhǔn)差
    如果你有一個(gè)DataFrame,在每列中都是相同類型的數(shù)據(jù),比如可能是一定時(shí)間內(nèi)的金融數(shù)據(jù),你可能需要找出水平方向上的均值:
df['mean'] = df.mean(axis=1)

或者找出垂直方向上的標(biāo)準(zhǔn)差:

df.std(axis=0)
  1. 將DataFrame轉(zhuǎn)換成Numpy數(shù)組
    將DataFrame中的數(shù)據(jù)轉(zhuǎn)換成數(shù)組的方式非常簡(jiǎn)單:
df.values

如果你想要保留表的形式:

df.as_matrix
  1. 用連接的方式組合DataFrames
    你可以將行或者列連接到一起,唯一的要求就是在相應(yīng)的軸上具有相同的shape。比如在垂直方向上連接行:
pd.concat([df_1, df_2], axis=0)

或者水平方向上連接列:

pd.concat([df_1, df_2], axis=1)
  1. 基于一個(gè)索引鍵來組合DataFrames
    在Pandas中合并做法跟SQL做法類似。如果你有兩個(gè)DataFrame擁有共同的鍵,比如一個(gè)披薩的‘order_id‘,你可以進(jìn)行內(nèi)連接(inner join),外連接(outer join),左鏈接(left join),右連接(right join),正如你能用SQL做到的一樣。
merged_df = df_1.merge(df_2, how='left', on='order_id')
  1. 將日期分裂成自己的日,周,月,年列
    首先,確認(rèn)數(shù)據(jù)時(shí)日期格式。然后用dt方法來抽取你需要的數(shù)據(jù)。
date = pd.to_datetime(df.date)
df['weekday'] = date.dt.weekday
df['year'] = date.dt.year
  1. 找出DataFrame中的Nan
    計(jì)算Nan出現(xiàn)的總數(shù):
df.isnull().sum().sum()

列舉每個(gè)列中的Nan數(shù):

df.isnull().sum()
  1. 填充Nan或者缺失數(shù)據(jù)
    多數(shù)機(jī)器學(xué)習(xí)算法不喜歡Nan這樣的值,所以你可能需要對(duì)他們進(jìn)行轉(zhuǎn)換。如果topping列有某些值缺失,我們可以用默認(rèn)值來填充。
df.topping = df.topping.fillna('Cheese')

或者我們可以在整個(gè)DataFrame中丟掉具有缺失值的行:

df = df.dropna(axis=0)
  1. 通過列的groupby函數(shù)抽取特征
    對(duì)列進(jìn)行分組是從數(shù)據(jù)抽取特征的很好的方式。當(dāng)你的數(shù)據(jù)可以計(jì)數(shù)或者可以用某種方式進(jìn)行量化,分組就特別有用了。例如,你可以根據(jù)topping列對(duì)披薩分組,然后計(jì)算每組中價(jià)格的均值。
df.groupby('topping')['discount'].apply(lambda x: np.mean(x))

或者可能你想要看一下某個(gè)值出現(xiàn)多少次:

df.groupby('topping')['discount'].apply(lambda x: x.count())

topping
Anchovies 3
Bell Pepper 1
Cheese 2
Olives 1
Pepperoni 3
Pineapple 2
Veggie 1
Name: discount, dtype: int64

  1. 創(chuàng)建Bins
    假設(shè)我們要根據(jù)不同的價(jià)格范圍將訂單歸到3個(gè)不同的桶里。這樣的做法非常適合講擁有噪聲的數(shù)據(jù)簡(jiǎn)化。
bins = [0, 5, 15, 30]
names = ['Cheap', 'Normal', 'Expensive']

df['price_point'] = pd.cut(df.price, bins, labels=names)
order_number price price_point
0 PZZA0000 12.99 Normal
1 PZZA0001 14.50 Normal
2 PZZA0002 19.99 Expensive
3 PZZA0003 20.99 Expensive
4 PZZA0004 21.99 Expensive
  1. 通過循環(huán)生成一個(gè)新列
    假設(shè)說我嗎想要將披薩配料分成‘蔬菜’和‘肉’兩類。處理這樣的名稱類值可以用一個(gè)循環(huán)來做到。(注意:你也可以用之前提到的apply函數(shù)來完成這個(gè)任務(wù)。
topping_type = []

for row in df.topping:
    if row in ['pepperoni', 'chicken', 'anchovies']:
        topping_type.append('meat')
    else:
        topping_type.append('vegetable')

df['topping_type'] = topping_type

注意:這種方法效率非常低下,應(yīng)該盡量避免。
種類有限的情況下,應(yīng)該盡量使用pandas的indexing方法。
比如:

df[df[['toppings'] == 'chicken']['topping_type'] = 'meat'
  1. 分塊方法來讀入大規(guī)模數(shù)據(jù)集
    有時(shí)你可能要處理一個(gè)很大的文件,超出了你內(nèi)存能夠處理的范圍,讓你的程序崩潰。在這種情況下,你可能需要將整個(gè)文件分成塊來讀入。
chunksize = 500
chunks = []
for chunk in pd.read_csv('pizza.csv', chunksize=chunksize):
    # Do stuff...
    chunks.append(chunk)

df = pd.concat(chunks, axis=0)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容