在品味了Pandas數(shù)據(jù)分析庫一段時間后威沫,我已經(jīng)總結(jié)了很長一個有用的代碼段的列表工腋,我發(fā)現(xiàn)我會一次又一次頻繁使用這些代碼段精拟。這些小建議可以節(jié)省很多用來瀏覽Pandas文檔的時間泼舱。
在本文中,我們從將披薩餅訂單數(shù)據(jù)填充dataframe開始矛渴。如果你是新接觸Pandas,這里給出一些關鍵的詞惫搏。
Dataframe 數(shù)據(jù)中添加了索引的行和列具温,類似電子表格或者數(shù)據(jù)庫的表。
Series= 數(shù)據(jù)的單獨一列
Axis:0==行筐赔,1==列
Shape:Dataframe中(行數(shù)铣猩,列數(shù))
- 導入CSV文件
對于read_csv函數(shù)有一千種選項可以用來簡化數(shù)據(jù)的前處理。沒有人想在清洗數(shù)據(jù)上花太多的時間茴丰,所以關鍵就在于你是否能在導入初始文件的時候就把事情搞定剂习。
df = pd.read_csv('pizza.csv')
需要解析日期?僅僅需要把處理方法傳遞個相應的列名较沪。
df = pd.read_csv('pizza.csv', parse_dates=['dates'])
只需要某些列鳞绕?
df = pd.read_csv('pizza.csv', usecols=['foo', 'bar'])
- 在Dataframe中探索數(shù)據(jù)
你想要做的第一件事可能就是數(shù)據(jù)是什么樣的。這里有幾種方法可以檢查Pandas的數(shù)據(jù)尸曼。
df.head() #先頭5行
df.tail() #最后5行
df.sample(5) #行的隨機采樣
df.shape #一個元組们何,包含行列數(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 |
- 在Dataframe中增加一個新列
簡單高效的做法就是在Dataframe中定義一個新列。下面的代碼給我們一個新列控轿,其中每一行的值都設為23冤竹。通常你需要用一個數(shù)組或者Series來設定列的內(nèi)容,這里數(shù)組或者Series的長度必須跟數(shù)據(jù)中的行數(shù)相匹配茬射。
df['new_column'] = 23
需要基于其他列來生產(chǎn)一個新列鹦蠕?
full_price = (df.price + df.discount)
df['original_price'] = full_price
需要根據(jù)某種順序來生成列?insert方法中第一個參數(shù)是列的位置在抛。下面的代碼將列放到Dataframe的開始位置钟病。
df.insert(0, 'original_price', full_price)
- 選擇一個具體單元格的值
所謂的單元格這里指位置的是行列交叉所在的數(shù)據(jù),跟Excel里的單元格是一個意思刚梭。你可能感覺這比較簡單肠阱,但是具體語法卻并不是那么直觀。在Pandas中有3個方法同時能做到這件事:.loc, .iloc, .ix——對新接觸的人而言朴读,這又更加了理解的難度屹徘。
通常我都是用.ix,因為這個方法允許整數(shù)和字符串混合使用衅金。首先輸入行的索引噪伊,然后是列的索引簿煌。
df.ix[2, 'topping']
你也可以通過點符號先選擇列,然后給定行的索引鉴吹,這樣看起來更清爽:
df.topping.ix[2]
上述的兩種方法都會返回單元格的值:
>>> 'Bell Pepper'
- 通過條件邏輯來篩選DataFrame
假設我們需要分析在topping列中包含菠蘿的訂單姨伟。
filtered_data = df[df.topping == 'pineapple']
或者我們要找的是高于一定價格線的訂單:
filtered_data = df[df.price > 11.99 ]
如果要同時滿足上述兩個條件我們怎么辦?僅僅將條件包裹成元組并將條件用位運算符連接起來就行拙寡。
filtered_data = df[(df.price > 11.99) & (df.topping == 'Pineapple')]
現(xiàn)在我們得到了包含菠蘿并且topping價格超過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 |
- 通過某一列來對DataFrame進行排序
下面的代碼意義不言自明,非常有用肆糕。
df.sort_values('price', axis=0, ascending=False)
- 對于列中的每行都應用一個函數(shù)
Python中匿名lambda函數(shù)非常適合這樣的任務般堆。假設我們需要用一個自定義的函數(shù)來計算DataFrame中每一行的稅金。Pandas中的apply函數(shù)運行我們將函數(shù)傳遞進來诚啃,在列中的每一個值上使用淮摔。在這個例子中,我們通過在價格數(shù)據(jù)上執(zhí)行一個自定義的函數(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 |
- 通過條件邏輯追加一個新列
numpy中的where函數(shù)在根據(jù)條件邏輯來抽取特征方面非常有用和橙。讓我們設想一下披薩店只有在銷售額度超過15美元時才有利潤。我們根據(jù)這個觀點創(chuàng)建一個新的列:
df['profitable'] = np.where(df['price']>=15.00, True, False)
- 找出復數(shù)列或者行的均值或者標準差
如果你有一個DataFrame造垛,在每列中都是相同類型的數(shù)據(jù)魔招,比如可能是一定時間內(nèi)的金融數(shù)據(jù),你可能需要找出水平方向上的均值:
df['mean'] = df.mean(axis=1)
或者找出垂直方向上的標準差:
df.std(axis=0)
- 將DataFrame轉(zhuǎn)換成Numpy數(shù)組
將DataFrame中的數(shù)據(jù)轉(zhuǎn)換成數(shù)組的方式非常簡單:
df.values
如果你想要保留表的形式:
df.as_matrix
- 用連接的方式組合DataFrames
你可以將行或者列連接到一起五辽,唯一的要求就是在相應的軸上具有相同的shape办斑。比如在垂直方向上連接行:
pd.concat([df_1, df_2], axis=0)
或者水平方向上連接列:
pd.concat([df_1, df_2], axis=1)
- 基于一個索引鍵來組合DataFrames
在Pandas中合并做法跟SQL做法類似。如果你有兩個DataFrame擁有共同的鍵杆逗,比如一個披薩的‘order_id‘乡翅,你可以進行內(nèi)連接(inner join),外連接(outer join)罪郊,左鏈接(left join)蠕蚜,右連接(right join),正如你能用SQL做到的一樣悔橄。
merged_df = df_1.merge(df_2, how='left', on='order_id')
- 將日期分裂成自己的日靶累,周,月橄维,年列
首先尺铣,確認數(shù)據(jù)時日期格式。然后用dt方法來抽取你需要的數(shù)據(jù)争舞。
date = pd.to_datetime(df.date)
df['weekday'] = date.dt.weekday
df['year'] = date.dt.year
- 找出DataFrame中的Nan
計算Nan出現(xiàn)的總數(shù):
df.isnull().sum().sum()
列舉每個列中的Nan數(shù):
df.isnull().sum()
- 填充Nan或者缺失數(shù)據(jù)
多數(shù)機器學習算法不喜歡Nan這樣的值,所以你可能需要對他們進行轉(zhuǎn)換澈灼。如果topping列有某些值缺失竞川,我們可以用默認值來填充店溢。
df.topping = df.topping.fillna('Cheese')
或者我們可以在整個DataFrame中丟掉具有缺失值的行:
df = df.dropna(axis=0)
- 通過列的groupby函數(shù)抽取特征
對列進行分組是從數(shù)據(jù)抽取特征的很好的方式。當你的數(shù)據(jù)可以計數(shù)或者可以用某種方式進行量化委乌,分組就特別有用了。例如遭贸,你可以根據(jù)topping列對披薩分組戈咳,然后計算每組中價格的均值。
df.groupby('topping')['discount'].apply(lambda x: np.mean(x))
或者可能你想要看一下某個值出現(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
- 創(chuàng)建Bins
假設我們要根據(jù)不同的價格范圍將訂單歸到3個不同的桶里壕吹。這樣的做法非常適合講擁有噪聲的數(shù)據(jù)簡化著蛙。
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 |
- 通過循環(huán)生成一個新列
假設說我嗎想要將披薩配料分成‘蔬菜’和‘肉’兩類。處理這樣的名稱類值可以用一個循環(huán)來做到耳贬。(注意:你也可以用之前提到的apply函數(shù)來完成這個任務踏堡。
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
注意:這種方法效率非常低下,應該盡量避免咒劲。
種類有限的情況下顷蟆,應該盡量使用pandas的indexing方法。
比如:
df[df[['toppings'] == 'chicken']['topping_type'] = 'meat'
- 分塊方法來讀入大規(guī)模數(shù)據(jù)集
有時你可能要處理一個很大的文件腐魂,超出了你內(nèi)存能夠處理的范圍帐偎,讓你的程序崩潰。在這種情況下蛔屹,你可能需要將整個文件分成塊來讀入削樊。
chunksize = 500
chunks = []
for chunk in pd.read_csv('pizza.csv', chunksize=chunksize):
# Do stuff...
chunks.append(chunk)
df = pd.concat(chunks, axis=0)