#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)


文章目录

    • 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的数据结构 #|数据分析与可视化(四)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,reindex可以修改(行)索引、列,或两个都修改。如果只传入一个序列,则结果中的行会重建索引。
更换索引 在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
参数by,如果传入函数,则对索引进行计算并分组;如果传入字典或者Series,则字典或者Series的值作为分组依据;如果传入Numpy数组,则数据元素作为分组依据;如果传入字符串或者字符串列表,则用这些字符串所代表的字段作为分组依据。
数据分组之后返回的是一个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 第一个和最后一个值
2.agg方法实现聚合数据:支持对每个分组应用某个函数。能直接对DataFrame进行函数应用操作。
#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学习基础一(统计分析基础)
文章图片

分类汇总求和

#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)
文章图片

交叉表:是一种特殊的透视表,主要用于计算分组频率。使用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

#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)
文章图片

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()

#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)
文章图片

# DataFrame df = pd.DataFrame({'normal':np.random.normal(size=50),'gamma':np.random.gamma(1, size=50)}) df.plot()

#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)
文章图片

柱状图 柱状图一般用来描述各类别之间的关系。在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))

#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)
文章图片

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')

#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)
文章图片

直方图和密度图 直方图用于频率分布,Y轴为数值或者比率。绘制直方图可以先大致观察数据的大致分布规律。Pandas中的直方图有由hist方法绘制。
核密度估计是对真实密度的估计,其过程是将数据的分布近似为一组核(如正态分布)。通过plot的kind='kde'进行绘制。
# 直方图【histbins参数是y轴的值 grid是否有表格】 obj1 = pd.Series(np.random.normal(size=80)) obj1.hist(bins=15, grid=False)

#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)
文章图片

#密度图【kind='kde'】 obj1.plot(kind='kde')

#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)
文章图片

散点图 散点图主要用来表示数据之间的规律,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')

#|数据分析与可视化(四)Pandas学习基础一(统计分析基础)
文章图片

    推荐阅读