今天整理pandas的iterrow函數和groupby函數,這兩個函數還是很常用的,在實際中的應用可以參考數據競賽修煉筆記之快手用戶活躍度的預測
1. pd.iterrows()函數
iterrows() 是在DataFrame中的行進行迭代的一個生成器,它返回每行的索引及一個包含行本身的對象。
所以,當我們在需要遍歷行數據的時候,就可以使用 iterrows()方法實現了。
df = pd.DataFrame(np.random.randn(3, 4), columns=list('ABCD'))
df
# 遍歷行
for index, row in df.iterrows(): # index表示索引, row是一個Series結構,可以通過列名或者列索引來獲取每一個元素
print(index)
print(row['A']) # 這樣是第一列的數據
print(row[-1]) # 最後一列的數據
print(row[1]) # 第二列的數據
這個函數比較簡單。
2. pd.groupby函數
這個函數的功能非常強大,類似於sql的groupby函數,對數據按照某一標準進行分組,然後進行一些統計。任何groupby操作都會涉及到下面的三個操作之一:
- Splitting:分割數據
- Applying:應用一個函數
- Combining:合併結果
在許多情況下,我們將數據分成幾組,並在每個子集上應用一些功能。在應用中,我們可以執行以下操作:
- Aggregation :計算一些摘要統計
- Transformation :執行一些特定組的操作
- Filtration:根據某些條件下丟棄數據
下面我們一一來看一看:
ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
'Year': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)
我們建立了這樣一個DataFrame
2.1 pandas對象可以拆分爲任何對象。 分分割方法有多種
- obj.groupby(‘key’)
- obj.groupby([‘key1’,‘key2’])
- obj.groupby(key,axis=1)
現在讓我們看看如何將分組對象應用於DataFrame對象
df.groupby('Team') # 按照Team屬性分組
# 查看分組
df.groupby('Team').groups # 第幾個是
## 結果:
{'Devils': Int64Index([2, 3], dtype='int64'),
'Kings': Int64Index([4, 6, 7], dtype='int64'),
'Riders': Int64Index([0, 1, 8, 11], dtype='int64'),
'Royals': Int64Index([9, 10], dtype='int64'),
'kings': Int64Index([5], dtype='int64')}
# 根據多列進行分組
df.groupby(['Team', 'Year']).groups
# 遍歷分組
grouped = df.groupby('Rank', as_index=False)
for name in grouped:
print(name)
2.2 獲取某一分組get_group方法
# 獲取某一分組
grouped = df.groupby('Year')
print(grouped.get_group(2014))
## 結果:
Team Rank Year Points
0 Riders 1 2014 876
2 Devils 2 2014 863
4 Kings 3 2014 741
9 Royals 4 2014 701
2.3 Aggregations(聚合)這個很重要
聚合函數返回每個組的單個聚合值。一旦創建了group by對象,就可以對分組數據執行多個聚合操作。
"""agg方法實現聚合, 相比於apply,可以同時傳入多個統計函數"""
# 針對同一列使用不同的統計方法
grouped = df.groupby('Year', as_index=False) # 這個as_index屬性,如果是False,就是SQL風格的統計輸出,如果是True,默認第一列變成了索引
print(grouped['Points'].agg({'mean':np.mean, 'std':np.std, 'max':np.max}))
# 針對不同的列使用不同的統計方法
print(grouped.agg({'Points':[np.mean, 'sum'], 'Rank':[np.max]}))
# 使用apply的話
print(grouped['Points'].apply(np.mean))
grouped.apply(lambda x: print(x))
"""查看每個組大小的另一種方法是應用size()函數"""
grouped = df.groupby('Team')
print(grouped.size())
print(grouped.count())
print(grouped.agg(np.size))
## 結果:
Team
Devils 2
Kings 3
Riders 4
Royals 2
kings 1
dtype: int64
Rank Year Points
Team
Devils 2 2 2
Kings 3 3 3
Riders 4 4 4
Royals 2 2 2
kings 1 1 1
Rank Year Points
Team
Devils 2 2 2
Kings 3 3 3
Riders 4 4 4
Royals 2 2 2
kings 1 1 1
2.4 Transformations
前面進行聚合運算的時候,得到的結果是一個以分組名爲 index 的結果對象。如果我們想使用原數組的 index 的話,就需要進行 merge 轉換。transform(func, args, *kwargs) 方法簡化了這個過程,它會把 func 參數應用到所有分組,然後把結果放置到原數組的 index 上(如果結果是一個標量,就進行廣播):
grouped = df.groupby('Team')
score = lambda x: (x - x.mean()) / x.std()*10
print(grouped.transform(score)) # 應用於原數組的index上
## 結果
Rank Year Points
0 -15.000000 -11.618950 12.843272
1 5.000000 -3.872983 3.020286
2 -7.071068 -7.071068 7.071068
3 7.071068 7.071068 -7.071068
4 11.547005 -10.910895 -8.608621
5 NaN NaN NaN
6 -5.773503 2.182179 -2.360428
7 -5.773503 8.728716 10.969049
8 5.000000 3.872983 -7.705963
9 7.071068 -7.071068 -7.071068
10 -7.071068 7.071068 7.071068
11 5.000000 11.618950 -8.157595
使用apply()處理的對象是一個個的類如DataFrame的數據表,然而agg()則每次只傳入一列,從列的角度進行輸出。
## 這裏可以看出這三者的區別:
print(grouped.transform(lambda x: print(x)))
print(grouped.agg(lambda x: print(x)))
print(grouped.apply(lambda x: print(x)))
2.5 Filtration
grouped.size() # 看一下分組後每個隊的個數
## 結果
Team
Devils 2
Kings 3
Riders 4
Royals 2
kings 1
dtype: int64
# 過濾到個數小於3的隊伍
print(df.groupby('Team').filter(lambda x: len(x) >= 3))
## 結果:
Team Rank Year Points
0 Riders 1 2014 876
1 Riders 2 2015 789
4 Kings 3 2014 741
6 Kings 1 2016 756
7 Kings 1 2017 788
8 Riders 2 2016 694
11 Riders 2 2017 690
參考博客: