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]) # 第二列的数据
这个函数比较简单。
这个函数的功能非常强大,类似于sql的groupby函数,对数据按照某一标准进行分组,然后进行一些统计。任何groupby操作都会涉及到下面的三个操作之一:
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)
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)
# 获取某一分组
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
聚合函数返回每个组的单个聚合值。一旦创建了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
前面进行聚合运算的时候,得到的结果是一个以分组名为 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)))
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