透视表的处理

透视表

  • 透视表是一种可以对数据动态排布并且分类汇总的表格格式。或许大多数人都在Excel使用过数据透视表,也体会到它的强大功能,而在pandas中它被称作pivot_table。

  • 透视表的优点:

    • 灵活性高,可以随意定制你的分析计算要求,比如聚合函数

    • 脉络清晰易于理解数据

    • 操作性强,报表神器

    • 更快(一旦设置之后)

    • 自行说明(通过查看代码,你将知道它做了什么)

pivot_table函数

  • index参数:分类汇总的分类条件
    • 每个pivot_table必须拥有一个index
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import pandas as pd
import numpy as np
df = pd.read_csv('./data/透视表-篮球赛.csv') # 哈登在对阵各队的情况数据表


# index 参数
# 想看看哈登不同主客场下的数据 会把不是数字的列剔除
df.pivot_table(index=['主客场'])
# 想看看哈登对阵同一对手在不同主客场下的数据,分类条件为对手和主客场
df.pivot_table(index=['主客场','对手'])
'''
Index就是层次字段,要通过透视表获取什么信息就按照相应的顺序设置字段,
'''


# values参数:需要对计算的数据进行筛选(你想看到的值)
df.pivot_table(index=['主客场'],values=['得分','篮板','助攻'])

#获取每个队主客场的总得分(在总得分的基础上又进行了对手的分类)
df.pivot_table(index='主客场',values='得分',columns='对手')


# aggfunc参数
# 还想获得哈登在主客场和不同胜负情况下的总得分、总篮板、总助攻时:
df.pivot_table(index=['主客场','胜负'],values=['得分','篮板','助攻'],aggfunc='sum')

""""
Columns类似Index可以设置列层次字段,它不是一个必要参数,作为一种分割数据的可选方式。
"""

# columns参数
df.pivot_table(index='主客场',columns="胜负")

# fill_value参数
#获取每个队主客场的总得分(在总得分的基础上又进行了对手的分类)
df.pivot_table(index='主客场',values='得分',columns='对手',aggfunc='sum',fill_value= 0 )

文档[透视表-篮球赛.csv][w]

pandas数据分组

1635038867340

groupby()函数

该方法提供的是分组聚合步骤中的拆分功能,能根据索引或字段对数据进行分组。其常 用参数与使用格式如下:

小示例

1
2
3
4
5
6
7
import pandas as pd

df = pd.read_excel('./data_former/forbes_2018.xlsx')

df.head()


Dataframe的分组

group.size() # 每组的个数

group.groups # 查看分组的情况

group.get_group(‘F’)根据分组后的名字选择分组数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
group = df.groupby('gender')  # 对整个数据进行分组,里面放列索引名或者一个列的series类型都可以 
>>>print(group)
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0B7BC710> #是一个对象
>>> list(group) # 查看分组了以后具体长什么样子

>>>group.size() # 每组的个数

gender
F 221 # 女性企业家 221
M 1810 # 男性企业家 1810
dtype: int64

>>> group.groups # 查看分组的情况 索引的情况
>>> group.get_group('F').head() #查看是男性企业家的数据, 根据分组后的名字选择分组数据

# 或者也可以进行索引重置 reset_index()
df = group.get_group('F').reset_index(drop = True)

对series进行分组

1
2
3
4
5
6
7
8
9
group  = df['age'].groupby(df['gender'])  # 特别注意的就是前面是series类型 分组的也是series类型.
>>>group # 理解 : 每个年龄也是有类别的 ,比如男和女

<pandas.core.groupby.generic.SeriesGroupBy object at 0x068D4F90>

>>>group.size()
>>> group.groups
>>> group.get_group('F')

统计函数

函数说明函数说明
count计算分组的数目,包括缺失值cumcount对每个分组的组员进行标记
head返回买组的前n个值size返回每组的大小
max返回每组的最大值min返回每组的最小值
mean返回每组的均值std返回每组的标准差
median返回每组的中位数sum返回每组的的和
1
2
3
4
5
6
7
8
9
10
11

group = df.groupby('gender')
list(group) # 查看详细数据
group.groups # 查看数据(字典形式) 数据是相对应的索引

f_group = group.get_group('F') # 查看F的所有数据(Dataframe形式!!!!!!!)
f_group['age'].mean() # 获取年龄的平均值
f_group['age'].max() # 获取年龄的最大值



分组遍历

获取的是 分组后的名字以及改组后的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
group = df.groupby('gender')
list(group) # 查看详细数据
group.groups # 查看数据(字典的形式)

# 分组后的名字是: F M
# 改组后的数据是: 每个index对应的值


for name ,data in group: #遍历对象
print(name)


for name ,data in group:
print(data) # 详细的数据


for name ,data in group:
print(name, data)


for name ,data in group:
f_mean = data['age'].mean() # 可以求出来年龄的平均值
f_max = data['age'].max() # 年龄的最大值
print(name, f_mean,f_max)




多列分组

1
2
3
4
5
6
group = df.groupby(['country','gender'])  # 根据country完以后再对gender分组 


list(group)
group.size()
>>>group.get_group(('Algeria','M')) # 可以把具体的数据筛选出来 .df形式

agg函数

聚合操作是groupby后非常常见的操作,会写SQL的朋友对此应该是非常熟悉了。聚合操作可以用来求和、均值、最大值、最小值等,下面的表格列出了Pandas中常见的聚合操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy  as np
company=["A","B","C"]

data=pd.DataFrame({
"company":[company[x] for x in np.random.randint(0,len(company),10)],
"salary":np.random.randint(5,50,10),
"age":np.random.randint(15,50,10)
}
)
data

# 如果我想求不同公司员工的平均年龄和平均薪水,可以按照下方的代码进行:
data.groupby("company").agg('mean')

# 如果想对针对不同的列求不同的值,比如要计算不同公司员工的平均年龄以及薪水的中位数,可以利用字典进行聚合操作的指定:

data.groupby('company').agg({'salary':'median','age':'mean'})

1635065078175

transform函数

transform是一种什么数据操作?和agg有什么区别呢?为了更好地理解transformagg的不同,下面从实际的应用场景出发进行对比。

在上面的agg中,我们学会了如何求不同公司员工的平均薪水,如果现在需要在原数据集中新增一列avg_salary,代表员工所在的公司的平均薪水(相同公司的员工具有一样的平均薪水),该怎么实现呢?如果按照正常的步骤来计算,需要先求得不同公司的平均薪水,然后按照员工和公司的对应关系填充到对应的位置,不用transform的话,实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy  as np
company=["A","B","C"]

data=pd.DataFrame({
"company":[company[x] for x in np.random.randint(0,len(company),10)],
"salary":np.random.randint(5,50,10),
"age":np.random.randint(15,50,10)
}
)

# 第一种方法:
avg_salary_dict = data.groupby('company')['salary'].mean().to_dict()
print(avg_salary_dict)
data['avg_salary'] = data['company'].map(avg_salary_dict)
# 第二种方法
data['avg_salary'] = data.groupby('company')['salary'].transform('mean')

img

过滤器filter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import numpy  as np
company=["A","B","C"]

data=pd.DataFrame({
"company":[company[x] for x in np.random.randint(0,len(company),10)],
"salary":np.random.randint(5,50,10),
"age":np.random.randint(15,50,10)
}
)
------------------
data.groupby('company')['age'].mean()
---------------------

def fun(x):
print(x)
print(x['salary'].mean())
return x['salary'].mean()> 27

data.groupby('company').filter(fun)



# 和apply进行对比

def fun(x):
# print(x)
# print(x['salary'].mean())
return x['salary'].mean()> 27

data.groupby('company').apply(fun)

[w]: blog_picture/resource/透视表-篮球赛.csv at main · xiryg/blog_picture (github.com)