文章目录
-
- 1. pandas的数据结构
-
-
- series:一维数组对象,通过索引来访问
- DataFrame:有一组有序的列,表格型的数据结构
- 索引对象
- 查看DataFrame的常用属性
-
- 2.Pandas的索引操作
-
-
-
- 重建索引
-
- 1.重建索引
- 3.reindex操作
- 更换索引
-
-
- 3.DataFrame数据的查询和编辑
-
-
-
- 查询【一般都是通过索引来操作的】
-
- 1.选取列
- 2.选取行
- 3.读取行和列
- 4.布尔选择
- 编辑【提取需要编辑的数据,重新赋值】
-
- 1.增加数据
- 2.删除数据
- 3.修改数据
-
-
- 4.pandas数据运算
-
-
-
-
- 算术运算
- 函数的应用和映射
- 排序
- 统计汇总
-
-
-
- 5.数据分组与聚合
-
-
-
-
- 数据分组
- 数据聚合:对分组后的数据进行计算,产生标量值的数据转换过程。
- 分组运算:包含聚合运算,聚合运算是数据转换的特例。
- 重要技巧: `groupby`之后直接`.reset_index()`可以得到一个没有多级索引的DataFram,之后可以通过`df.rename({‘old_col1’:‘new_col1’,‘old_col2’:‘new_col2’,…})`重命名
-
-
-
- 6.数据透视表
-
-
-
-
- 透视表
- 交叉表:是一种特殊的透视表,主要用于计算分组频率。使用Pandas提供的crosstab函数可以制作。
-
-
-
- 7.Pandas可视化
-
-
-
-
- 线形图
- 柱状图
- 直方图和密度图
- 散点图
-
-
-
1. pandas的数据结构
文章图片
Series:类似于数组
DataFrame:类似于表格
Panel:Excel多表单Sheet【不常用】
series:一维数组对象,通过索引来访问 1.创建:可通过列表和字典来创建
import pandas as pd
import numpy as np
s1 = pd.Series([1,4,'ab',0])
s2 = pd.Series({'A':'111', 'B':'你好', 'C':'345'})
print(s1,'\t',s2)
#>>>>>>>输出结果:
01
14
2ab
30
dtype: objectA111
B你好
C345
dtype: object
2.索引
(1)列表建立Series对象时,没有指定index,会自己生成整数型索引,可用使用索引切片技术;指定index时,Series会有两种描述某数据的手段,自己生成的整数位置索引和建立Series对象时给定的index索引(标签); dtype用来给定数据类型。
import pandas as pd
list1 = [1,3,5,7]
s1 = pd.Series(list1, index=['a1', 'b1', 'c1', 'd1'], dtype='object')
print('s1 index索引取值',s1['a1'])
print('s1 位置取值',s1[0])#>>>>>>>结果:
s1 index索引取值 1
s1 位置取值 1
(2)字典建立Series对象时,不指定index,默认会用字典键有序排列来做索引;指定index时,如果键值与指定的index不匹配,会生成NaN(非数字);给定的index索引可用通过赋值方式修改
import pandas as pd
dic = {
'a':'中国',
'b':'日本',
'd':'美国'
}
s = pd.Series(dic, index=['a', 'b', 'c', 'd'])
print(s)s.index = ['A', 'B', 'C','D']#>>>>>>>结果:a中国
b日本
cNaN
d美国
dtype: object
修改index: A中国
B日本
CNaN
D美国
dtype: object
DataFrame:有一组有序的列,表格型的数据结构 1.创建:最常用的是直接传入一个由等长列表或者NumPy数组组成的字典来形成DataFrame。
2.特性:会自动加上索引,且全部列会被有序排列,如果columns指定列名序列,则按指定列名排列;index给出行标签;如果传入的列在数据中找不到,会产生NaN值。
data = https://www.it610.com/article/{'name':['张飞', '孙尚香', '韩信', '貂蝉', '马超'],
'location':['游走', '下路', '打野', '中单', '上单'],
'dynasty':['蜀', '蜀', '战国', '汉', '蜀'],
'year':[1999, 2000, 2020, 2050, 3030]
}
df = pd.DataFrame(data)
print(df)
#>>>>>>结果:
name location dynastyyear
0张飞游走蜀1999
1孙尚香下路蜀2000
2韩信打野战国2020
3貂蝉中单汉2050
4马超上单蜀3030
df = pd.DataFrame(data, columns=['name','location','dynasty','address','year'],index=['a','b','c','d','e'])
print(df)
#>>>>>>>>结果:name location dynasty addressyear
a张飞游走蜀NaN1999
b孙尚香下路蜀NaN2000
c韩信打野战国NaN2020
d貂蝉中单汉NaN2050
e马超上单蜀NaN3030
索引对象 1.pandas的索引对象负责管理轴标签和其它元数据信息(例如轴名称等),构建Series和DataFrame时,所用到的任何数组或其它序列的标签,都会被转换成一个Index。
print(df.index)
print(df.columns)
#>>>>>>>结果:
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
Index(['name', 'location', 'dynasty', 'address', 'year'], dtype='object')
2.Index长的像数组,功能类似于一个固定大小的集合。不可修改保证Index在多个数据结构间的安全共享。
print('name' in df.columns)
df.index=['1','2','3','4','5']
df.columns=['a','b','c','d','e']
print(df)
#>>>>>>>结果:
True
abcde
1张飞游走蜀NaN1999
2孙尚香下路蜀NaN2000
3韩信打野战国NaN2020
4貂蝉中单汉NaN2050
5马超上单蜀NaN3030
【#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)】3.索引的方法和属性
方法 | 属性 |
---|---|
append | 连接另一个Index对象,产生一个新的Index对象 |
diff | 计算差集并得到一个Index |
intersection | 计算交集 |
union | 计算并集 |
isin | 计算一个指示各值是否都包含在参数集合中的布尔型数组 |
delete | 删除索引i处的元素,并得到新的Index |
drop | 删除传入的值,并得到新的Index |
insert | 将元素插入索引i处,并得到新的索引 |
is_monotonic | 当各元素均大于或等于前一个元素时,返回True |
is.unique | 当Index没有重复值时,返回True |
unique | 计算Index中唯一值的数组 |
df.index.insert(1,'w')
#>>>>>>>结果:
Index(['1', 'w', '2', '3', '4', '5'], dtype='object')
查看DataFrame的常用属性
属性 | 描述 |
---|---|
values | 元素,返回二维嵌套列表 |
index | 索引,返回Index |
columns | 列名 |
dtypes | 类型 |
ndim | 维度 |
shape | 形状 |
size | 元素的个数 |
print(df)
print("--------------")
print(df.values())
print("--------------")
print(df.index())
print("--------------")
print(df.columns())
print("--------------")
print(df.dtypes())
print("--------------")
print(df.ndim())
print("--------------")
print(df.shape())
print("--------------")
print(df.size())
#>>>>>>>结果:
abcde
1张飞游走蜀NaN1999
2孙尚香下路蜀NaN2000
3韩信打野战国NaN2020
4貂蝉中单汉NaN2050
5马超上单蜀NaN3030
--------------
[['张飞' '游走' '蜀' nan 1999]
['孙尚香' '下路' '蜀' nan 2000]
['韩信' '打野' '战国' nan 2020]
['貂蝉' '中单' '汉' nan 2050]
['马超' '上单' '蜀' nan 3030]]
--------------
Index(['1', '2', '3', '4', '5'], dtype='object')
--------------
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
--------------
aobject
bobject
cobject
dobject
eint64
dtype: object
--------------
2
--------------
(5, 5)
--------------
25
2.Pandas的索引操作 索引对象是无法修改的,因此重建索引是指对索引的重新排序而不是重新命名,如果某个索引值不存在的话会引入缺失值。
重建索引 1.重建索引
import pandas as pd
import numpy as np
obj = pd.Series([3,4.5,9,0], index = ['a','c','b','d'])
print(obj)
obj.reindex(['a','b','c','d','e'])
》》》》》》结果:
a3.0
c4.5
b9.0
d0.0
dtype: float64
a3.0
b9.0
c4.5
d0.0
eNaN
dtype: float64###### 2.填充重建索引时引入的缺失值【前向与后向填充】```python
#填充缺失值
obj.reindex(['a','c','c','d','e'], fill_value=https://www.it610.com/article/10)
》》》》》》结果:
a3.0
c4.5
c4.5
d0.0
e10.0
dtype: float64
#前向填充和后向填充:method='ffill\bfill'
obj1 = pd.Series(['blue','red','black'], index = [0,2,4])
obj1.reindex(np.arange(6), method = 'ffill')
>>>>>结果:
0blue
1blue
2red
3red
4black
5black
dtype: objectobj2 = pd.Series(['blue','red','black'], index = [0,2,4])
obj2.reindex(np.arange(6), method = 'bfill')
>>>>>结果:
0blue
1red
2red
3black
4black
5NaN
dtype: object
3.reindex操作
参数 | 说明 |
---|---|
index | 用于索引的新序列 |
method | 插值(填充)方式【ffill[pad]、bfill[backfill]】 |
fill_value | 缺失值替换值 |
limit | 最大填充数 |
leve copy | 在Multiindex的指定级别上匹配简单索引,否则取决其子集默认为True,无论如何都复制;如果为False,则新旧相等时不复制 |
更换索引 在DataFrame数据中,如果不想用默认的行索引,则可以在创建时通过Index参数来设置。有时希望将列数据作为索引,可以用set_index方法来实现。与set_index相反的是reset_index。
data = https://www.it610.com/article/{'name':['张飞', '孙尚香', '韩信', '貂蝉', '马超'],
'location':['游走', '下路', '打野', '中单', '上单'],
'dynasty':['蜀', '蜀', '战国', '汉', '蜀'],
'year':[1999, 2000, 2020, 2050, 3030]
}
df = pd.DataFrame(data, columns=['name','location','dynasty','address','year'],index=['a','b','c','d','e'])
df1 = df.set_index('dynasty')
print(df1)name location addressyear
dynasty
蜀张飞游走NaN1999
蜀孙尚香下路NaN2000
战国韩信打野NaN2020
汉貂蝉中单NaN2050
蜀马超上单NaN3030
3.DataFrame数据的查询和编辑 查询【一般都是通过索引来操作的】 1.选取列 通过列索引标签或者属性的方式可以单独获取DataFrame的列数据,返回数据类型为Series。在选取列时不能使用切片的方式,超过一个列名用
df[['列名1','列名2']]
#选取列
import pandas as pd
import numpy as np
data = https://www.it610.com/article/{'name':['张三','李四','王麻子'],
'age':[21,19,23],
'address':['兰州','上海','北京']
}
df = pd.DataFrame(data)
print(df)
w1 = df['name']
print("以列名取一列数据:\n", w1)
w2 = df[['name','age']]
print("以列名取两份数据:\n", w2)nameage address
0张三21兰州
1李四19上海
2王麻子23北京
以列名取一列数据:
0张三
1李四
2王麻子
Name: name, dtype: object
以列名取两份数据:
nameage
0张三21
1李四19
2王麻子23
2.选取行 通过行索引或者行索引位置切片形式获取行数据【从0开始的,左闭右开】。DataFrame提供的head【开头开始】和tail【结尾】可以取连续多行数据,sample可以随机抽取并显示数据
#取行从0开始的
print('显示前两行:\n', df[:2])
print('显示2行:\n', df[1:2])
#head从第一行取,默认前五行
print(df.head())
print(df.head(1))
#tail默认最后五行可以带数字取最后的
print(df.tail())
print(df.tail(1))
#sample随机抽取n行显示
print(df.sample(2))
显示前两行:
nameage address
0张三21兰州
1李四19上海
显示2行:
nameage address
1李四19上海
nameage address
0张三21兰州
1李四19上海
2王麻子23北京
nameage address
0张三21兰州
nameage address
0张三21兰州
1李四19上海
2王麻子23北京
nameage address
2王麻子23北京
nameage address
2王麻子23北京
1李四19上海
3.读取行和列 切片选取行限制比较大,取单独的几行数据可以采用Pandas提供的iloc和loc方法实现。
用法:DataFrame.loc(行索引位置, 列索引位置)
? DataFrame.loc(行索引名称或条件, 列索引名称)
#loc
data = https://www.it610.com/article/{'name':['张飞', '孙尚香', '韩信', '貂蝉', '马超'],
'location':['游走', '下路', '打野', '中单', '上单'],
'dynasty':['蜀', '蜀', '战国', '汉', '蜀'],
'year':[1999, 2000, 2020, 2050, 3030]
}
df1 = pd.DataFrame(data, columns=['name','location','dynasty','address','year'],index=['a','b','c','d','e'])
df2 = df1.set_index('dynasty')
print(df2)
print("取name和year两列的数据:\n",df2.loc[:,['name','year']])
print("取汉,战国行中name,year的数据:\n",df2.loc[['汉','战国'],['name','year']])
name location addressyear
dynasty
蜀张飞游走NaN1999
蜀孙尚香下路NaN2000
战国韩信打野NaN2020
汉貂蝉中单NaN2050
蜀马超上单NaN3030
取name和year两列的数据:
nameyear
dynasty
蜀张飞1999
蜀孙尚香2000
战国韩信2020
汉貂蝉2050
蜀马超3030
取汉,战国行中name,year的数据:
nameyear
dynasty
汉貂蝉2050
战国韩信2020
#iloc[索引0开始]
print("显示前两列:\n", df2.iloc[:, 2])
print("显示第1和第3行的第2列:\n", df2.iloc[[1,3],[0]])
显示前两列:
dynasty
蜀1999
蜀2000
战国2020
汉2050
蜀3030
Name: year, dtype: int64
显示第1和第3行的第二列:
name
dynasty
蜀孙尚香
汉貂蝉
也可以使用ix方法实现行和列的选择,同时支持索引标签和索引位置取值。
4.布尔选择 用选择符不等于(!=)、与(&)、或(|)
df3 = df2[df2['year'] == 3030]
print(df3,type(df3))#返回dataframe型
df2['name']=='孙尚香'#返回布尔类型
name locationyear
dynasty
蜀马超上单3030 dynasty
蜀False
蜀True
战国False
汉False
蜀False
Name: name, dtype: bool
编辑【提取需要编辑的数据,重新赋值】 1.增加数据 增加一行通过append方法传入字典结构数据即可,增加列时为增加的列赋值即可创建一个新的列,具体给值要对应,不然会报错
#插入一行数据append
#加列并赋值
df1['C'] = 10
df1['age'] = [24,33,19,40,80]data1 = {
'name':'李白',
'location':'打野',
'dynasty':'唐',
'year':'1909'
}
df1.append(data1,ignore_index=True)
name location dynastyyearCage
0张飞游走蜀19991024
1孙尚香下路蜀20001033
2韩信打野战国20201019
3貂蝉中单汉20501040
4马超上单蜀30301080name location dynasty year C age
0 张飞 游走 蜀 1999 10.0 24.0
1 孙尚香 下路 蜀 2000 10.0 33.0
2 韩信 打野 战国 2020 10.0 19.0
3 貂蝉 中单 汉 2050 10.0 40.0
4 马超 上单 蜀 3030 10.0 80.0
5 李白 打野 唐 1909 NaN
2.删除数据 删除数据直接用drop方法,行列数据通过axis参数设置默认为0删除行,1删除列。默认数据删除不修改原数据,如果在原数据上删除加入参数inplace=True即可。
#删除数据的行和列没有指定inplace=True,删除不是在原数据上操作的
df1.drop('C',axis=1)
print(df1)
name location dynastyyearCage
0张飞游走蜀19991024
1孙尚香下路蜀20001033
2韩信打野战国20201019
3貂蝉中单汉20501040
4马超上单蜀30301080df1.drop('C',axis=1,inplace=True)
print(df1)name location dynastyyearage
0张飞游走蜀199924
1孙尚香下路蜀200033
2韩信打野战国202019
3貂蝉中单汉205040
4马超上单蜀303080
3.修改数据 对选择的数据进行赋值就可以了。**修改数据是对DataFrame值的修改,无法撤销。**如新列赋值。
4.pandas数据运算 算术运算 如果有相同索引则进行算术运算,如果没有则会进行数据对齐,但会引入缺失值。对于DataFrame类型,数据对齐的操作会同时发生在行和列上。
import pandas as pd
import numpy as np##Series相加
obj1 = pd.Series([1,4,-1,9,0,-8], index=['a','b','d','e','f','g'])
obj2 = pd.Series([4,9,0,-4,-1,10], index=['a','c','d','e','f','h'])
print("obj1:\n",obj1)
print("obj2:\n",obj2)print(obj1+obj2)
obj1:
a1
b4
d-1
e9
f0
g-8
dtype: int64
obj2:
a4
c9
d0
e-4
f-1
h10
dtype: int64
a5.0
bNaN
cNaN
d-1.0
e5.0
f-1.0
gNaN
hNaN
dtype: float64
## DataFrame行和列均会对齐给NaN值
import pandas as pd
import numpy as np
df1 = pd.DataFrame(np.arange(12).reshape(3,4), columns=['a','b','c','d'], index=['A','B','C'])
df2 = pd.DataFrame(np.arange(9).reshape(3,3), columns=['a','c','d'], index=['A','B','D'])
print("df1:\n",df1)
print("df1:\n",df2)
print(df1+df2)
df1:
abcd
A0123
B4567
C891011
df1:
acd
A012
B345
D678
abcd
A0.0 NaN3.05.0
B7.0 NaN10.012.0
CNaN NaNNaNNaN
DNaN NaNNaNNaN
函数的应用和映射 1.定义函数进行较为复杂的数据处理过程
(1).
map
函数:将函数套入到Series的每个元素中(2).
apply
函数:将函数套用到DataFrame的行和列上,行和列通过axis参数指定。(3).
applymap
函数:将函数套用到DataFrame的每个元素上。匿名函数:
lambda 参数列表 : 关于参数的表达式
e.g:lambda x,y:x+y:该函数的输入是x和y,输出是x+y的值
#去掉水果价格中的元字
data = https://www.it610.com/article/{'fruit':['apple','grape','banana'],'price':['30元','40元','50元']}
df = pd.DataFrame(data)
print(df)
def f1(x):
return x.split('元')[0]#按’元‘分割 取第一个位置的
df['price'] = df['price'].map(f1)#map函数会循环给所给数据的每一个元素执行f1函数
print(df)
fruit price
0apple30元
1grape40元
2banana50元
fruit price
0apple30
1grape40
2banana50
##apply函数套用到df的行与列axis[轴]axis=1 按行运算
df = pd.DataFrame(np.random.randn(3,3), columns=['a','b','c'], index=['app','win','mic'])
print(df)
df.apply(np.mean,axis=1)
abc
app -0.336255 -0.446342 -0.888068
win2.7427482.432790 -1.444682
mic0.567298 -0.2686660.039183app-0.556888
win1.243619
mic0.112605
dtype: float64
##applymap套用到df每个元素 对整个df进行批量处理
#匿名函数:lambda 参数列表 : 关于参数列表的表达式(一行)【输入是传递进来的参数列表的值,输出是根据表达式计算所得的值】
print(df)
df.applymap(lambda x:'%.3f'%x)
abc
app -0.336255 -0.446342 -0.888068
win2.7427482.432790 -1.444682
mic0.567298 -0.2686660.039183a b c
app -0.336 -0.446 -0.888
win 2.743 2.433 -1.445
mic 0.567 -0.269 0.039
排序 在Series中,通过
sort_index
方法对索引进行排序,通过sort_values
对数值进行排序,默认升序,降序加参数ascending=False
。##排序Seriesdataframesort_index([ascending=False]) 默认升序,False降序sort_values([by='列名'])
obj = pd.Series([-1,0,-9,9,5],index=['a','c','b','e','d'])
print('值排序:\n',obj.sort_values())
print('索引降序:\n',obj.sort_index(ascending=False))值排序:
b-9
a-1
c0
d5
e9
dtype: int64
索引降序:
e9
d5
c0
b-9
a-1
dtype: int64
对于DataFrame的排序,通过指定axis轴的方向,使用
sort_index
对行或列索引进行排序,若要进行列排序,用sort_values(by='列名')
。#DataFrame
print(df)
print(df.sort_values(by='a'))
abc
app -0.336255 -0.446342 -0.888068
win2.7427482.432790 -1.444682
mic0.567298 -0.2686660.039183
abc
app -0.336255 -0.446342 -0.888068
mic0.567298 -0.2686660.039183
win2.7427482.432790 -1.444682
统计汇总 1.数据汇总:
sum
函数可以对每列求和汇总。axis=1
可以实现按行汇总##数据汇总axis=1是按行默认按列
print(df)
print('按列汇总:\n',df.sum())
print('按行汇总:\n',df.sum(axis=1))
abc
app -0.336255 -0.446342 -0.888068
win2.7427482.432790 -1.444682
mic0.567298 -0.2686660.039183
按列汇总:
a2.973791
b1.717783
c-2.293567
dtype: float64
按行汇总:
app-1.670665
win3.730856
mic0.337815
dtype: float64
2.数据的描述与统计
描述性统计表:
方法名称 | 说明 | 方法名称 | 说明 |
---|---|---|---|
min | 最小值 | max | 最大值 |
mean | 均值 | ptp | 极差 |
std | 标准差 | var | 方差 |
cov | 协方差 | sem | 标准误差 |
median | 中位数 | mode | 众数 |
skew | 样本偏度 | kurt | 样本峰度 |
quantitle | 四分位数 | count | 非空值数目 |
describe | 统计描述 | mad | 平均绝对离差 |
对于类别型特征的描述性统计,可以使用频数统计表。unique获取不重复的值。value_counts实现频数统计。
#数据的描述与统计
obj = pd.Series([1,2,3,0,5,6,0,0,3])
print('去重:\n',obj.unique())
print('频数统计:\n',obj.value_counts())
去重:
[1 2 3 0 5 6]
频数统计:
03
32
11
21
51
61
dtype: int64
5.数据分组与聚合 数据分组 1.groupby方法:
DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False)
参数名称 | 参数说明 |
---|---|
by | 可以传入函数、字典、Series等,用于分组的依据条件 |
axis | 0或者1,表示操作的轴方向默认按列操作,取1按行操作 |
level | 接收int或者索引名,代表标签所在的级别,默认None |
as_index | 接收boolean,表示聚合后的聚合标签是否以DataFrame的索引输出,默认True |
sort | 接收boolean,对分组依据和分组标签排序,默认True |
group_keys | 接收boolean,表示是否显示分组标签的名称,默认True |
squeeze | 接收Boolean,表示是否在允许情况下对数据进行降维操作,默认False |
数据分组之后返回的是一个groupby对象,可以调用该对象的方法如size返回一个含有分组大小的Series。
#取df['data1']这一列数据并按df['key1']这一列的数据来分组分完之后a:3 ,b:2
import numpy as np
import pandas as pd
##groupby()
df = pd.DataFrame({
'key1':['a','a','b','b','a'],
'key2':[1,0,1,1,0],
'data1':np.random.randn(5),
'data2':np.random.randn(5)
})
print(df)
grouped = df['data1'].groupby(df['key1'])
print(grouped.size())
print(grouped.mean())
key1key2data1data2
0a10.4105180.204681
1a0 -0.558132 -0.008501
2b1 -0.008334 -1.935630
3b1 -0.4817430.775196
4a00.5976050.561882
key1
a3
b2
Name: data1, dtype: int64
key1
a0.149997
b-0.245038
Name: data1, dtype: float64
2.按列名分组:DataFrame数据的列索引名可以作为分组键,但是用于分组的对象必须是DataFrame本身。不然会报错找不到索引名称。
#按列索引名称分组
grouped1 = df.groupby('key1').size()
grouped2 = df.groupby('key1').mean()
print(grouped1)
grouped2
key1
a3
b2
dtype: int64key2 data1 data2
key1
a 0.333333 0.149997 0.252688
b 1.000000 -0.245038 -0.580217
3.按列表或元组分组:分组键还可以是和DataFrame行数相等的列表或者元组,相当于把列表或者元组当成DataFrame的一列,然后分组。
##所给的按列表或元组
w = ['w','w','y','w','y']
df.groupby(w).sum()key2 data1 data2
w 2 -0.629356 0.971377
y 1 0.589272 -1.373748
4.按字典分组:如果原始的DataFrame中分组信息难以确定或不存在,则可以通过字典结构定义一个分组信息。
#定义一个字典来分组分组信息:不区分大小写来分组
df = pd.DataFrame(np.random.normal(size=(6,5)), index=['a','b','A','B','c','C'])
print(df)
dic = {
"a":'one',
"b":'two',
"c":'three',
"A":'one',
"B":'two',
"C":'three'
}
x = df.groupby(dic)
print(x.sum())01234
a -0.4225621.962075 -0.489384 -1.304302 -1.109478
b1.134703 -0.358548 -1.3730250.851012 -0.302279
A -0.196233 -0.1924630.2860700.872550 -0.835654
B -0.038677 -0.130829 -0.599642 -0.201865 -1.849057
c -0.033203 -0.512046 -0.4145640.5165911.191699
C -1.1457680.176744 -0.1601641.435075 -0.124890
01234
one-0.6187951.769613 -0.203314 -0.431753 -1.945131
three -1.178971 -0.335301 -0.5747281.9516661.066808
two1.096026 -0.489377 -1.9726670.649148 -2.151336
5.按函数分组:类似于字典,通过映射关系来进行分组
#函数
def judge(x):
if x>=0:
return 'a'
else:
return 'b'
df = pd.DataFrame(np.random.randn(4,4))
print(df)
print(df[3].groupby(df[3].map(judge)).sum())
0123
00.714710 -1.1809710.1773711.257526
1 -0.4653900.8224701.7679480.740839
20.1949280.658354 -0.053870 -0.657892
31.001120 -1.1950801.122340 -1.813876a1.998365
b-2.471768
Name: 3, dtype: float64
数据聚合:对分组后的数据进行计算,产生标量值的数据转换过程。 1.聚合函数:在聚合运算中,空值不参加计算。
函数 | 使用说明 |
---|---|
count | 计数 |
sum | 求和 |
mean | 平均值 |
median | 中位数 |
std、var | 无偏标准差和方差 |
min、max | 最小、最大值 |
prod | 求积 |
first、last | 第一个和最后一个值 |
#agg
## 使用agg求出当前数据对应的统计量
data = https://www.it610.com/article/pd.read_excel('D:\python\数据分析与可视化\第四章:pandas统计分析基础\data\\testdata.xls')
print(data.head())
print('求当前数据的各项统计量:\n',data[['淋巴细胞计数','白细胞计数']].agg([np.sum, np.mean]))
## 使用agg函数分别求各字段不同的统计量
print('求个字段的不同统计量:\n',data.agg({'淋巴细胞计数':np.mean, '白细胞计数':np.std}))## 计算不同字段不同数目的统计量
print('计算不同字段不同数目的统计量:\n',data.agg({'淋巴细胞计数':np.mean, '白细胞计数':[np.std, np.mean]}))## 统计不同性别人群的血小板计数的平均值
print('统计不同性别人群的血小板计数:\n',data.groupby('性别')['血小板计数'].agg(np.mean))
## 返回的数据不希望以分组键为索引as_index=False实现
print('统计不同性别人群的血小板计数:\n',data.groupby('性别',as_index=False)['血小板计数'].agg(np.mean))序号性别身份证号 是否吸烟 是否饮酒 开始从事某工作年份体检年份淋巴细胞计数白细胞计数细胞其它值\
01女****1982080000否否2009年20172.48.5NaN
12女****1984110000否否2015年20171.85.8NaN
23男****1983060000否否2013年20172.05.6NaN
34男****1985040000否否2014年20172.56.6NaN
45男****1986040000否否2014年20171.35.2NaN血小板计数
0248.0
1300.0
2195.0
3252.0
4169.0
求当前数据的各项统计量:
淋巴细胞计数白细胞计数
sum4280.2700006868.008100
mean3.8491646.176266
求个字段的不同统计量:
淋巴细胞计数3.849164
白细胞计数12.043418
dtype: float64
计算不同字段不同数目的统计量:
淋巴细胞计数白细胞计数
mean3.8491646.176266
stdNaN12.043418
统计不同性别人群的血小板计数:
性别
女212.687636
男194.727417
Name: 血小板计数, dtype: float64
统计不同性别人群的血小板计数:
性别血小板计数
0女212.687636
1男194.727417
分组运算:包含聚合运算,聚合运算是数据转换的特例。 1.transform方法:将运算分不到每一行
# 分组运算
## transform运算分布到每一行
data.groupby('性别')['血小板计数'].transform('mean').sample(5)915194.727417
1039194.727417
1062194.727417
95194.727417
416212.687636
Name: 血小板计数, dtype: float64
2.apply方法:类似于agg方法,可以将函数应用于每一列
## apply函数应用到每列axis=1应用到每行
data.groupby(['性别','是否吸烟'])['血小板计数'].apply(np.mean)性别是否吸烟
女否212.133188
是297.333333
男否194.236749
是195.210175
重要技巧:
groupby
之后直接.reset_index()
可以得到一个没有多级索引的DataFram,之后可以通过df.rename({‘old_col1’:‘new_col1’,‘old_col2’:‘new_col2’,…})
重命名 df1= df.groupby([‘date’])[‘price’].agg({‘sum’,‘count’}).reset_index()
6.数据透视表 数据透视表(Pivot Table)是数据分析中常见的工具之一,根据一个或多个键值对对数据进行聚合,根据列或行的分组键将数据划分到各个区域。
透视表 groupby()、pivot_table():均可以实现透视功能。
pivot_table(data, values=None, index=Nane, columns=None, aggfunc='mean', fill_value=https://www.it610.com/article/None, margins=False, dropna=True, margins_name='All')
参数 | 使用说明 |
---|---|
data | 接收DataFrame,创建表的数据 |
values | 接收string,指定聚合的数据字段,默认全部 |
index | 接收string或list,行分组键 |
columns | 接收string或list,列分组键 |
aggfunc | 接收函数,表示聚合函数,默认mean |
margins | 接收boolean,表示汇总功能开关 |
dropna | 接收boolean,表示是否删除掉全为NaN的列,默认False |
import numpy as np
import pandas as pd
data = https://www.it610.com/article/pd.DataFrame({'k1':['a','b','c','a','c','d','e','b','d','c','a','c'],
'k2':['one','two','three','one','two','three','three','three','one','two','one','two'],
'w':np.random.rand(12),'y':np.random.randn(12)
})
print(data)
data.pivot_table(index='k1',columns='k2')
k1k2wy
0aone0.505038 -0.692691
1btwo0.760838 -1.147333
2cthree0.279918 -0.511096
3aone0.3619620.605746
4ctwo0.6056190.217253
5dthree0.7089271.632609
6ethree0.760684 -0.099134
7bthree0.6787670.814771
8done0.062156 -1.247613
9ctwo0.8006723.008441
10aone0.958991 -0.014311
11ctwo0.9437060.486200w y
k2 one three two one three two
k1
a 0.608664 NaN NaN -0.033752 NaN NaN
b NaN 0.678767 0.760838 NaN 0.814771 -1.147333
c NaN 0.279918 0.783332 NaN -0.511096 1.237298
d 0.062156 0.708927 NaN -1.247613 1.632609 NaN
e NaN 0.760684 NaN NaN -0.099134 NaN
由于复制过不来表格 就截屏了 前面遇到过好几次透视表了,groupby出来的都是透视表。
文章图片
分类汇总求和
文章图片
交叉表:是一种特殊的透视表,主要用于计算分组频率。使用Pandas提供的crosstab函数可以制作。
crosstab(index, columns ,values=None, rownames=None, colnames=None, aggfunc=None, margins=False,dropna=True,normalize=False )
参数 | 使用说明 |
---|---|
index | 接收string或者list,表示行索引键,没有默认值 |
columns | 接收string或者list,表示列索引键,没有默认值 |
values | 接收array,表示聚合数据,默认为None |
rownames | 表示行分组键名,无默认 |
colnames | 表示列分组键名,无默认 |
aggfunc | 接收函数,表示聚合函数,默认None |
margins | 接收boolean,表示汇总功能开关 |
dropna | 接收boolean,表示删除的全为NaN的列,默认False |
normalize | 接收boolean,表示是否对值进行标准化,默认False |
##交叉表
pd.crosstab(data.k1,data.k2,margins=True)#在边框处增加汇总k2 one three two All
k1
a 3 0 0 3
b 0 1 1 2
c 0 1 3 4
d 1 1 0 2
e 0 1 0 1
All 4 4 4 12
文章图片
7.Pandas可视化 Pandas中集成了Matplotlib中的基础组件,绘图便捷。
线形图 线形图一般用于描述两组数据之间的趋势。Pandas库中的Series和DataFrame中都有绘制各类图表的plot方法,默认绘制线形图。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
#线形图Series
obj = pd.Series(np.random.normal(size=10))
obj.plot()
文章图片
# DataFrame
df = pd.DataFrame({'normal':np.random.normal(size=50),'gamma':np.random.gamma(1, size=50)})
df.plot()
文章图片
柱状图 柱状图一般用来描述各类别之间的关系。在plot函数中加入参数
kind='bar'
,如果类别较多,可以绘制水平柱状图(kind='barh'
)。在DataFrame中绘制柱状图,对于DataFrame数据而言,每一行的值会成为一组。
# 柱状图kind='bar'/'barh'类别多少rot:标签角度
stu = {'name':['孙尚香','李白','韩信','马克','妲己'],
'sex':['female','male','male','male','female'],
'age':[19,20,22,21,25]
}
df = pd.DataFrame(stu)
print(df['sex'].value_counts())
print(df['sex'].value_counts().plot(kind='bar' ,rot=30))
文章图片
DataFrame数据对象的柱状图:观察图很显然那个图和数据直接是有很明显的对应关系的,一行是一组图。
# 直接DataFrame作图类别多水平柱状图
df = pd.DataFrame(np.random.randint(1,100, size=(4,4)), index=['a','b','c','d'], columns=['I1','I2','I3','I4'])
df.plot(kind='barh')
文章图片
直方图和密度图 直方图用于频率分布,Y轴为数值或者比率。绘制直方图可以先大致观察数据的大致分布规律。Pandas中的直方图有由hist方法绘制。
核密度估计是对真实密度的估计,其过程是将数据的分布近似为一组核(如正态分布)。通过
plot的kind='kde'
进行绘制。# 直方图【histbins参数是y轴的值 grid是否有表格】
obj1 = pd.Series(np.random.normal(size=80))
obj1.hist(bins=15, grid=False)
文章图片
#密度图【kind='kde'】
obj1.plot(kind='kde')
文章图片
散点图 散点图主要用来表示数据之间的规律,
plot(kind='scatter')
#kind = 'scatter'不能是Sreries还得给定x与y
df1 = pd.DataFrame(np.arange(10), columns=['A'])
df1['B'] = 2*df1['A']+2
print(df1)
df1.plot(kind='scatter',x='A',y='B')
文章图片
推荐阅读
- 数据分析|机器学习多元线性回归模型(公式推导以及代码实现)
- 机器学习|机器学习(2)-朴素贝叶斯的理解和代码实现
- numpy|numpy库的使用-读取数据
- python|机器学习--朴素贝叶斯分类器(python手动实现)
- python|python-pandas dataframe正则筛选包含某字符串的列数据str.contains()
- Python全栈系列[更新中]|Python零基础入门篇 - 53 - 文件的读取
- Python全栈系列[更新中]|Python零基础入门篇 - 51 - 文件的创建与写入
- Python全栈系列[更新中]|Python零基础入门篇 - 52 - 文件操作的避坑指南
- Python全栈系列[更新中]|Python零基础入门篇 - 33 - 你了解编程范式吗(面向过程编程与面向对象编程的区别又是什么?)