1.介绍 1.1 Pandas是什么? Pandas
是一个基于NumPy
的分析结构化数据的工具集,NumPy
为其提供了高性能的数据处理能力。Pandas
被普遍用于数据挖掘和数据分析,同时也提供数据清洗、数据I/O
、数据可视化等辅助功能。
1.2 安装 $ conda install pandas $ pip install pandas
2.数据结构 学习Pandas
之前,一般都需要先了解下其对应的数据结构,方便后面理解和使用,DataFrame(数据框)
和Series(序列)
是Pandas
库中两个最基本、最重要的数据结构。它们提供了灵活且高效的数据操作方法,使得数据分析和处理变得更加简单和可行。
Series(序列)
: 是一种类似于一维数组的数据结构,它可以存储任意类型的数据,并附带有标签(label
),这些标签可以用于索引。Series
可以看作是由两个数组组成,一个是数据值的数组,一个是与之相关的标签的数组。
DataFrame
: 是一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame
即有行索引也有列索引,可以被看做是由Series
组成的字典。
2.1 Series Series
是一个对象,其对应的构造函数所需参数如下:
def __init__ ( self, data=None , index=None , dtype: Dtype | None = None , name=None , copy: bool | None = None , fastpath: bool = False , )
1.参数说明
data
: 指的是输入数据,当输入数据类型不同时,会有不同的操作,如下:
如果是一个数组(如列表或 NumPy
数组),那么它将成为 Series
的数据。
如果是一个字典,字典的键将成为 Series
的索引,字典的值将成为 Series
的数据。
如果是一个标量值,它将被广播到整个 Series
。
index
: 指定Series
的索引;如果不提供,将创建默认的整数索引,从0开始。
dtype
: 指定Series
的数据类型; 如果不提供,将自动推断数据类型。
name
: 为Series
指定一个名称。
copy
: 如果为True
,则复制输入数据。默认情况下不复制。
@注意: Series的所有数据都是同一种数据类型.
2. 使用示例 import numpy as npimport pandas as pdif __name__ == '__main__' : print ("基于标量-默认索引-s_var: \n" , pd.Series(18 , name='s_var' , dtype=np.float32)) print ("基于标量-指定索引-s_var2: \n" , pd.Series(18 , name='s_var2' , dtype=np.float32, index=['小花' ])) print ("------------------------分割线----------------------------" ) list_var = ["Go" , "Python" , "PHP" , "Java" ] s_list = pd.Series(list_var, name='s_list' ) print ("基于列表-默认索引-s_list: \n" , s_list) index_var = ["a" , "b" , "c" , "d" ] s_list2 = pd.Series(list_var, index=index_var, name='s_list2' ) print ("基于列表-指定索引-s_list2: \n" , s_list2) print ("------------------------分割线----------------------------" ) dict_var = {'a' : 'Go' , 'b' : 'Python' , 'c' : 'PHP' , 'd' : 'Java' } s_dict = pd.Series(dict_var, name='s_dict' ) print ("基于字典-s_dict: \n" , s_dict) print ("------------------------分割线----------------------------" ) s_np = pd.Series(np.arange(5 , 10 ), name='s_np' ) print ("基于numpy-s_np: \n" , s_np) """ 基于标量-默认索引-s_var: 0 18.0 Name: s_var, dtype: float32 基于标量-指定索引-s_var2: 小花 18.0 Name: s_var2, dtype: float32 ------------------------分割线---------------------------- 基于列表-默认索引-s_list: 0 Go 1 Python 2 PHP 3 Java Name: s_list, dtype: object 基于列表-指定索引-s_list2: a Go b Python c PHP d Java Name: s_list2, dtype: object ------------------------分割线---------------------------- 基于字典-s_dict: a Go b Python c PHP d Java Name: s_dict, dtype: object ------------------------分割线---------------------------- 基于numpy-s_np: 0 5 1 6 2 7 3 8 4 9 Name: s_np, dtype: int64 """
@注意: 当指定索引(index)参数时,需要保证索引的数量和输入数据的数量保持一致,否则会报错: ValueError: Length of values (..) does not match length of index (..)
2.2 DataFrame DataFrame
可以看作多个Series
的集合,每个Series
都可以拥有各自独立的数据类型,因此,DataFrame
没有自身唯一的数据类型,自然也就没有dtype
属性了。不过,DataFrame
多了一个dtypes
属性,这个属性的类型是Series
类。除了dtypes
属性,DataFrame
的values
属性、index
属性、columns
属性也都非常重要。
DataFrame
对应的构造函数如下:
def __init__ ( self, data=None , index: Axes | None = None , columns: Axes | None = None , dtype: Dtype | None = None , copy: bool | None = None , )
1. 参数说明
data
: 指的是输入数据,当输入数据类型不同时,会有不同的操作,如下:
如果是一个字典,字典的值可以是列表、数组或其他字典,它们将成为 DataFrame
的列。
如果是一个数组或列表,它将被转换为二维数组,每一行将成为 DataFrame
的一行。
如果是另一个DataFrame
,则将创建一个副本。
index
: 指定DataFrame
的索引;如果不提供,将创建默认的整数索引,从0开始。
columns
: 指定 DataFrame
的列索引。如果不提供,将使用字典的键(如果数据是字典)或整数序列。
dtype
: 指定DataFrame
的数据类型; 如果不提供,将自动推断数据类型。
copy
: 如果为True
,则复制输入数据。默认情况下不复制。
2. 使用示例 import numpy as npimport pandas as pdif __name__ == '__main__' : data_dict = {'Name' : ['Alice' , 'Bob' , 'Charlie' ], 'Age' : [25 , 30 , 35 ], 'City' : ['New York' , 'San Francisco' , 'Los Angeles' ]} df_dict = pd.DataFrame(data_dict) print ("1.使用字典创建DataFrame: \n" , df_dict) data_numpy = np.array([[1 , 'Alice' ], [2 , 'Bob' ], [3 , 'Charlie' ]]) df_numpy = pd.DataFrame(data_numpy, columns=['ID' , 'Name' ]) print ("2.使用NumPy数组创建DataFrame: \n" , df_numpy) data_existing_df = {'Name' : ['Alice' , 'Bob' , 'Charlie' ], 'Age' : [25 , 30 , 35 ], 'City' : ['New York' , 'San Francisco' , 'Los Angeles' ]} existing_df = pd.DataFrame(data_existing_df) df_existing_df = pd.DataFrame(existing_df) print ("3.使用DataFrame创建DataFrame:" , df_existing_df) print ("# ---------------- 属性信息打印 ----------------" ) print ("DataFrame.dtypes:\n" , df_existing_df.dtypes) print ("DataFrame.values:" , df_existing_df.values) print ("DataFrame.index:" , df_existing_df.index) print ("DataFrame.columns:" , df_existing_df.columns) """ 1.使用字典创建DataFrame: Name Age City 0 Alice 25 New York 1 Bob 30 San Francisco 2 Charlie 35 Los Angeles 2.使用NumPy数组创建DataFrame: ID Name 0 1 Alice 1 2 Bob 2 3 Charlie 3.使用DataFrame创建DataFrame: Name Age City 0 Alice 25 New York 1 Bob 30 San Francisco 2 Charlie 35 Los Angeles # ---------------- 属性信息打印 ---------------- DataFrame.dtypes: Name object Age int64 City object dtype: object DataFrame.values: [['Alice' 25 'New York'] ['Bob' 30 'San Francisco'] ['Charlie' 35 'Los Angeles']] DataFrame.index: RangeIndex(start=0, stop=3, step=1) DataFrame.columns: Index(['Name', 'Age', 'City'], dtype='object') """
3.基础用法 从数据结构构成上,我们知道DataFrame
是由多个Series
的组成, 在实际使用中也是使用DataFrame
的场景居多,所以后续主要学习DataFrame
数据结构的使用;
3.1 准备数据 import pandas as pdif __name__ == '__main__' : data_dict = { "成绩" : [90 , 88 , 80 , 95 ], "年龄" : [23 , 19 , 20 , 33 ], "身高" : [175 , 165 , 170 , 173 ], "体重" : [71.5 , 50.5 , 66.5 , 75.3 ], "城市" : ["北京" , "南京" , "上海" , "上海" ], } names = ["小明" , "小英" , "李思" , "王老五" ] data_res = pd.DataFrame(data_dict, index=names) print ("学员信息:\n" , data_res)""" 学员信息: 成绩 年龄 身高 体重 城市 小明 90 23 175 71.5 北京 小英 88 19 165 50.5 南京 李思 80 20 170 66.5 上海 王老五 95 33 173 75.3 上海 """
3.2 访问数据 if __name__ == '__main__' : head_data = data_res.head(1 ) print ("------ 第一行: ------\n" , data_res.head(1 )) print ("------ 最后一行: ------\n" , data_res.tail(1 )) print ("------ data_res[1:3]: ------ \n" , data_res[1 :3 ]) print ("------ 返回某一行,小英数据: ------ \n" , data_res["小英" :"小英" ]) print ("------ 返回某一列,所有城市: ------ \n" , data_res["城市" ]) print ("------ 同时选择行和列,小明、李思的成绩和年龄: ------ \n" , data_res.loc[["小明" , "李思" ], ["成绩" , "年龄" ]]) print ("------ 条件选择| 年龄<20: ------ \n" , data_res[data_res["年龄" ] < 20 ]) search_a = data_res[(data_res["城市" ] == "上海" ) & (data_res["成绩" ] > 80 )] print ("------ 条件选择| 城市=上海 & 成绩 > 80: ------ \n" , search_a) print ("------ 根据标签,访问具体值-王老五的身高: " , data_res.at["王老五" , "身高" ]) print ("------ 根据位置,访问具体值-王老五的身高: " , data_res.iat[3 , 2 ]) """ ------ 第一行: ------ 成绩 年龄 身高 体重 城市 小明 90 23 175 71.5 北京 ------ 最后一行: ------ 成绩 年龄 身高 体重 城市 王老五 95 33 173 75.3 上海 ------ data_res[1:3]: ------ 成绩 年龄 身高 体重 城市 小英 88 19 165 50.5 南京 李思 80 20 170 66.5 上海 ------ 返回某一行,小英数据: ------ 成绩 年龄 身高 体重 城市 小英 88 19 165 50.5 南京 ------ 返回某一列,所有城市: ------ 小明 北京 小英 南京 李思 上海 王老五 上海 Name: 城市, dtype: object ------ 同时选择行和列,小明、李思的成绩和年龄: ------ 成绩 年龄 小明 90 23 李思 80 20 ------ 条件选择| 年龄<20: ------ 成绩 年龄 身高 体重 城市 小英 88 19 165 50.5 南京 ------ 条件选择| 城市=上海 & 成绩 > 80: ------ 成绩 年龄 身高 体重 城市 王老五 95 33 173 75.3 上海 ------ 根据标签,访问具体值-王老五的身高: 173 ------ 根据位置,访问具体值-王老五的身高: 173 """
3.3 编辑数据 import pandas as pdif __name__ == '__main__' : print ("#-------------- 修改具体值 -------------------" ) print ("标签赋值--变更前小英年龄:" , data_res.at["小英" , "年龄" ]) data_res.at["小英" , "年龄" ] = 18 print ("标签赋值--变更后小英年龄:" , data_res.at["小英" , "年龄" ]) print ("位置赋值--变更前小英年龄:" , data_res.iat[1 , 1 ]) data_res.iat[1 , 1 ] = 24 print ("位置赋值--变更后小英年龄:" , data_res.iat[1 , 1 ]) print ("#-------------- 修改整列值 -------------------" ) print ("修改整列值--变更前:" , data_res["成绩" ]) data_res["成绩" ] = 100 print ("修改整列值--变更后:" , data_res["成绩" ])""" #-------------- 修改具体值 ------------------- 标签赋值--变更前小英年龄: 19 标签赋值--变更后小英年龄: 18 位置赋值--变更前小英年龄: 18 位置赋值--变更后小英年龄: 24 #-------------- 修改整列值 ------------------- 修改整列值--变更前: 小明 90 小英 88 李思 80 王老五 95 Name: 成绩, dtype: int64 修改整列值--变更后: 小明 100 小英 100 李思 100 王老五 100 Name: 成绩, dtype: int64 """
3.4 追加&删除 import pandas as pdif __name__ == '__main__' : data_res["爱好" ] = ["旅游" , "游戏" , "篮球" , "学习" ] print ("------------------ 增加一列: ------------------ \n " , data_res) new_data = data_res.drop(["城市" , "成绩" , "体重" ], axis=1 ) print ("------------------drop 删除多列: ------------------ \n " , new_data) new_row = {"成绩" : 100 , "年龄" : 30 , "身高" : 185 , "体重" : 80.5 , "城市" : "蜀国" , "爱好" : "练武" } new_dataframe = pd.DataFrame([new_row], index=["赵云" ]) data_res_new = pd.concat([data_res, new_dataframe]) print ("------------------ 增加行后: ------------------ \n " , data_res) new_data = data_res_new.drop(["小明" , "王老五" ], axis=0 ) print ("------------------drop 删除多行: ------------------ \n " , new_data) """ ------------------ 增加一列: ------------------ 成绩 年龄 身高 体重 城市 爱好 小明 90 23 175 71.5 北京 旅游 小英 88 19 165 50.5 南京 游戏 李思 80 20 170 66.5 上海 篮球 王老五 95 33 173 75.3 上海 学习 ------------------drop 删除多列: ------------------ 年龄 身高 爱好 小明 23 175 旅游 小英 19 165 游戏 李思 20 170 篮球 王老五 33 173 学习 ------------------ 增加行后: ------------------ 成绩 年龄 身高 体重 城市 爱好 小明 90 23 175 71.5 北京 旅游 小英 88 19 165 50.5 南京 游戏 李思 80 20 170 66.5 上海 篮球 王老五 95 33 173 75.3 上海 学习 ------------------drop 删除多行: ------------------ 成绩 年龄 身高 体重 城市 爱好 小英 88 19 165 50.5 南京 游戏 李思 80 20 170 66.5 上海 篮球 赵云 100 30 185 80.5 蜀国 练武 """
函数说明:
drop
: 用于删除行或列的函数。它可以在 DataFrame
或 Series
上使用,用于删除指定的行或列,并返回一个新的对象,原始对象保持不变。axis
参数用于指定是删除行还是列,其中 axis=0
表示行,axis=1
表示列。默认情况下,axis=0
。
concat
: 将数据沿着某个轴进行拼接,可以按行拼接(垂直拼接)或按列拼接(水平拼接),使用参数axis
指定拼接的轴,axis=0
表示按行拼接(垂直拼接),axis=1
表示按列拼接(水平拼接),默认是按照行拼接 。
3.5 排序数据 import pandas as pdif __name__ == '__main__' : by_age_asc = data_res.sort_values(by="年龄" , ascending=True ) print ("-------------------- 根据年龄升序排序(原始数据不变) --------------------:\n" , by_age_asc) data_res.sort_values(by="成绩" , ascending=False , inplace=True ) print ("-------------------- 根据成绩降序排序(修改原始数据) --------------------:\n" , data_res) by_age_score = data_res.sort_values(by=["年龄" , "成绩" ], ascending=False ) print ("-------------------- 根据多列排序(先按年龄,再根据成绩) --------------------:\n" , by_age_score) rank_data = data_res.rank(ascending=False ) print ("------------- 使用rank排序,返回当前数据在所属列的排名名次 : -------------\n" , rank_data)""" -------------------- 根据年龄升序排序(原始数据不变) --------------------: 成绩 年龄 身高 体重 城市 小英 88 19 165 50.5 南京 李思 80 20 170 66.5 上海 小明 90 23 175 71.5 北京 王老五 95 33 173 75.3 上海 -------------------- 根据成绩降序排序(修改原始数据) --------------------: 成绩 年龄 身高 体重 城市 王老五 95 33 173 75.3 上海 小明 90 23 175 71.5 北京 小英 88 19 165 50.5 南京 李思 80 20 170 66.5 上海 -------------------- 根据多列排序(先按年龄,再根据成绩) --------------------: 成绩 年龄 身高 体重 城市 王老五 95 33 173 75.3 上海 小明 90 23 175 71.5 北京 李思 80 20 170 66.5 上海 小英 88 19 165 50.5 南京 ------------- 使用rank排序,返回当前数据在所属列的排名名次 : ------------- 成绩 年龄 身高 体重 城市 王老五 1.0 1.0 2.0 1.0 3.5 小明 2.0 2.0 1.0 2.0 2.0 小英 3.0 4.0 4.0 4.0 1.0 李思 4.0 3.0 3.0 3.0 3.5 """
函数说明:
sort_values
函数用于排序 DataFrame
或 Series
,具体参数如下:
def sort_values ( self, by: IndexLabel, *, axis: Axis = 0 , ascending: bool | list [bool ] | tuple [bool , ...] = True , inplace: bool = False , kind: str = "quicksort" , na_position: str = "last" , ignore_index: bool = False , key: ValueKeyFunc = None , ) -> DataFrame | None :
by: 指定排序的列名或列名的列表。如果是多个列,可以传递一个包含多个列名的列表。按照列表中的列的顺序进行排序。
axis: 指定排序的轴,axis=0
表示按行排序,axis=1
表示按列排序。默认为 0。
ascending: 指定排序的顺序,True
表示升序,False
表示降序。可以是一个布尔值或布尔值的列表,用于指定每个列的排序顺序。默认为 True
。
inplace: 如果为 True
,则在原地修改对象而不返回新对象;如果为 False
(默认),则返回一个新对象,原对象保持不变。
kind: 指定排序算法的种类,可选值有 quicksort(快速排序)、mergesort(归并排序)、heapsort(堆排序)
;默认为 quicksort
。
na_position: 指定缺失值的位置,可选值有 first
(在前)和 last
(在后)。默认为 last
。
ignore_index: 如果为 True
,则重新设置索引,忽略现有索引。默认为 False
。
key: 用于排序的函数,可以是函数、类实例或类的方法。如果指定,将用该函数的返回值进行排序。
4.数据运算 4.1 数据摘要 import pandas as pdif __name__ == '__main__' : data_dict = { "水果" : ["香蕉" , "苹果" , "葡萄" , "橘子" ], "进货价" : [1.25 , 0.56 , 3.5 , 1.15 ], "最低价" : [1.55 , 0.80 , 4.0 , 2.00 ], "最高价" : [3.45 , 1.5 , 6.5 , 4.15 ], "数量" : [600 , 500 , 400 , 500 ], } fruit_data = pd.DataFrame(data_dict) print ("--------------- 原始数据 -----------------" ) print (fruit_data) print ("--------------- 查看数据的统计摘要 -----------------" ) print (fruit_data.describe())""" --------------- 原始数据 ----------------- 水果 进货价 最低价 最高价 数量 0 香蕉 1.25 1.55 3.45 600 1 苹果 0.56 0.80 1.50 500 2 葡萄 3.50 4.00 6.50 400 3 橘子 1.15 2.00 4.15 500 --------------- 查看数据的统计摘要 ----------------- 进货价 最低价 最高价 数量 count 4.00000 4.000000 4.00000 4.000000 mean 1.61500 2.087500 3.90000 500.000000 std 1.29302 1.367708 2.06438 81.649658 min 0.56000 0.800000 1.50000 400.000000 25% 1.00250 1.362500 2.96250 475.000000 50% 1.20000 1.775000 3.80000 500.000000 75% 1.81250 2.500000 4.73750 525.000000 max 3.50000 4.000000 6.50000 600.000000 """
输出结果说明:
count: 非缺失值的数量。
mean: 平均值。
std: 标准差,衡量数据的离散程度。
min: 最小值。
25%: 第一四分位数,数据中的 25% 的值小于此值。
50%: 中位数(第二四分位数),数据中的中间值。
75%: 第三四分位数,数据中的 75% 的值小于此值。
max: 最大值。
4.2 统计运算 import pandas as pdif __name__ == '__main__' : data_dict = { "水果" : ["香蕉" , "苹果" , "葡萄" , "橘子" ], "进货价" : [1.25 , 0.56 , 3.5 , 1.15 ], "最低价" : [1.55 , 0.80 , 4.0 , 2.00 ], "最高价" : [3.45 , 1.5 , 6.5 , 4.15 ], "数量" : [600 , 500 , 400 , 500 ], } fruit_data = pd.DataFrame(data_dict) print ("--------------- 原始数据 -----------------" ) print (fruit_data) print ("--------------- 均值运算 -----------------" ) print ("[数量]这一列均值: " , fruit_data["数量" ].mean()) print ("[进货价]这一列均值: " , fruit_data["进货价" ].mean()) print ("--------------- 极值运算 -----------------" ) print ("[进货价]这一列最小值: " , fruit_data["进货价" ].min ()) print ("[进货价]这一列最大值: " , fruit_data["进货价" ].max ()) print ("--------------- 累和运算 -----------------" ) print (fruit_data[["数量" , "进货价" ]].cumsum()) print ("--------------- 广播运算-数量列减半 -----------------" ) fruit_data["数量" ] = fruit_data["数量" ] / 2 print (fruit_data) """ --------------- 原始数据 ----------------- 水果 进货价 最低价 最高价 数量 0 香蕉 1.25 1.55 3.45 600 1 苹果 0.56 0.80 1.50 500 2 葡萄 3.50 4.00 6.50 400 3 橘子 1.15 2.00 4.15 500 --------------- 均值运算 ----------------- [数量]这一列均值: 500.0 [进货价]这一列均值: 1.6150000000000002 --------------- 极值运算 ----------------- [进货价]这一列最小值: 0.56 [进货价]这一列最大值: 3.5 --------------- 累和运算 ----------------- 数量 进货价 0 600 1.25 1 1100 1.81 2 1500 5.31 3 2000 6.46 --------------- 广播运算-数量列减半 ----------------- 水果 进货价 最低价 最高价 数量 0 香蕉 1.25 1.55 3.45 300.0 1 苹果 0.56 0.80 1.50 250.0 2 葡萄 3.50 4.00 6.50 200.0 3 橘子 1.15 2.00 4.15 250.0 """
4.3 自定义函数 apply()
函数的存在,可以让我更灵活的处理数据,它可以接收一个我们实现的函数,然后对数据进行自定义处理,具体参数如下:
def apply ( self, func: AggFuncType, axis: Axis = 0 , raw: bool = False , result_type: Literal ["expand" , "reduce" , "broadcast" ] | None = None , args=( ), **kwargs, ):
func: 要应用的函数。可以是函数、字符串函数名称、NumPy
函数或字典。
axis: 指定应用函数的轴,axis=0
表示按列(默认),axis=1
表示按行。
raw: 如果为 True
,则将每一行或列作为一维数组传递给函数。如果为 False
(默认),则将每一行或列作为 Series
传递给函数。
result_type: 指定返回结果的数据类型,可以是 'expand'、'reduce'、'broadcast'
或 None
。默认为 None
。
args: 传递给函数的位置参数。
**kwargs
: 传递给函数的关键字参数。
import randomimport pandas as pddef custom_compute (x: pd.Series ): """ 变更指定列信息 :param x: :return: """ if x.name == "最低价" : return x + random.randint(1 , 100 ) / 100 elif x.name == "数量" : return x * 1.5 return xdef total_cost (x: pd.Series ): """ 计算总成本 :param x: :return: """ money = x["进货价" ] * x["数量" ] print ("{} 进货价:{} 数量:{} 成本:{}" .format (x["水果" ], x["进货价" ], x["数量" ], money)) return moneyif __name__ == '__main__' : data_dict = { "水果" : ["香蕉" , "苹果" , "葡萄" , "橘子" ], "进货价" : [1.25 , 0.56 , 3.5 , 1.15 ], "最低价" : [1.55 , 0.80 , 4.0 , 2.00 ], "最高价" : [3.45 , 1.5 , 6.5 , 4.15 ], "数量" : [600 , 500 , 400 , 500 ], } fruit_data = pd.DataFrame(data_dict) print ("--------------- 原始数据 -----------------" ) print (fruit_data) print ("--------------- 自定义函数运算:最低价加上随机数,数量*1.5 -----------------" ) new_data = fruit_data.apply(custom_compute) print (new_data) print ("--------------- 自定义函数运算:计算变更后的总成本 -----------------" ) total_money = new_data.apply(total_cost, axis=1 ).sum () print ("变更后的总成本:" , total_money) """ --------------- 原始数据 ----------------- 水果 进货价 最低价 最高价 数量 0 香蕉 1.25 1.55 3.45 600 1 苹果 0.56 0.80 1.50 500 2 葡萄 3.50 4.00 6.50 400 3 橘子 1.15 2.00 4.15 500 --------------- 自定义函数运算:最低价加上随机数,数量*1.5 ----------------- 水果 进货价 最低价 最高价 数量 0 香蕉 1.25 1.86 3.45 900.0 1 苹果 0.56 1.11 1.50 750.0 2 葡萄 3.50 4.31 6.50 600.0 3 橘子 1.15 2.31 4.15 750.0 --------------- 自定义函数运算:计算变更后的总成本 ----------------- 香蕉 进货价:1.25 数量:900.0 成本:1125.0 苹果 进货价:0.56 数量:750.0 成本:420.00000000000006 葡萄 进货价:3.5 数量:600.0 成本:2100.0 橘子 进货价:1.15 数量:750.0 成本:862.4999999999999 变更后的总成本: 4507.5 """
4.4 分组运算 通过函数 groupby
,可以按照某一列或多列的值将数据集分成多个组,并在这些组上应用各种操作。
import randomimport pandas as pdif __name__ == '__main__' : names = ["小明" , "小丽" , "小龙" , "小花" ] dates = ["2023-05" , "2023-06" , "2023-07" , "2023-08" , "2023-09" , "2023-10" ] subjects = ["语文" , "数学" , "英语" ] rows = 5 data_dict = { "姓名" : [random.choice(names) for _ in range (rows)], "日期" : [random.choice(dates) for _ in range (rows)], "学科" : [random.choice(subjects) for _ in range (rows)], "成绩" : [random.randint(60 , 100 ) for _ in range (rows)], } data = pd.DataFrame(data_dict) print ("-------------- 原始数据 ------------------" ) print (data) print ("-------------- 根据姓名分组 ------------------" ) for name, group in data.groupby("姓名" ): print ("====== 姓名:{} ====== \n" .format (name)) print (group) print ("-------------- 分组后统计总分数 ------------------" ) sum_data = data.groupby("姓名" )["成绩" ].sum () print (sum_data) print ("-------------- 分组后,针对多列执行不同的统计 ------------------" ) agg_data = data.groupby("姓名" ).agg({"成绩" : ["max" , "mean" , "min" ], "学科" : "count" }) print (agg_data) """ -------------- 原始数据 ------------------ 姓名 日期 学科 成绩 0 小丽 2023-05 数学 76 1 小龙 2023-06 数学 74 2 小花 2023-09 英语 62 3 小丽 2023-05 英语 68 4 小明 2023-10 语文 87 -------------- 根据姓名分组 ------------------ ====== 姓名:小丽 ====== 姓名 日期 学科 成绩 0 小丽 2023-05 数学 76 3 小丽 2023-05 英语 68 ====== 姓名:小明 ====== 姓名 日期 学科 成绩 4 小明 2023-10 语文 87 ====== 姓名:小花 ====== 姓名 日期 学科 成绩 2 小花 2023-09 英语 62 ====== 姓名:小龙 ====== 姓名 日期 学科 成绩 1 小龙 2023-06 数学 74 -------------- 分组后统计总分数 ------------------ 姓名 小丽 144 小明 87 小花 62 小龙 74 Name: 成绩, dtype: int64 -------------- 分组后,针对多列执行不同的统计 ------------------ 成绩 学科 max mean min count 姓名 小丽 76 72.0 68 2 小明 87 87.0 87 1 小花 62 62.0 62 1 小龙 74 74.0 74 1 """