Python库学习(十一):数据分析Pandas[上篇]


1.介绍

1.1 Pandas是什么?

Pandas是一个基于NumPy的分析结构化数据的工具集,NumPy为其提供了高性能的数据处理能力。Pandas被普遍用于数据挖掘和数据分析,同时也提供数据清洗、数据I/O、数据可视化等辅助功能。

  • Github_Star 40k : https://github.com/pandas-dev/pandas
  • 中文文档: https://www.pypandas.cn/docs/
  • 官方文档: https://pandas.pydata.org/docs/getting_started/comparison/index.html

1.2 安装

# 使用Anaconda
$ conda install pandas

# 使用pip 
$ 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 np
import pandas as pd

if __name__ == '__main__':
    # -------------- 基于标量,创建Series --------------
    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("------------------------分割线----------------------------")
    # -------------- 基于列表,创建Series --------------
    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("------------------------分割线----------------------------")
    # -------------- 基于字典,创建Series --------------
    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("------------------------分割线----------------------------")
    # -------------- 基于np,创建Series --------------
    s_np = pd.Series(np.arange(510), 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属性,DataFramevalues属性、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 np
import pandas as pd

if __name__ == '__main__':
    # 使用字典创建DataFrame
    data_dict = {'Name': ['Alice''Bob''Charlie'],
                 'Age': [253035],
                 'City': ['New York''San Francisco''Los Angeles']}

    df_dict = pd.DataFrame(data_dict)
    print("1.使用字典创建DataFrame: n", df_dict)

    # 使用NumPy数组创建DataFrame
    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)

    # 使用另一个DataFrame创建DataFrame
    data_existing_df = {'Name': ['Alice''Bob''Charlie'],
                        'Age': [253035],
                        'City': ['New York''San Francisco''Los Angeles']}

    existing_df = pd.DataFrame(data_existing_df)

    # 创建新的DataFrame,复制已存在的DataFrame
    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 pd

if __name__ == '__main__':
    # 使用字典创建DataFrame
    data_dict = {
        "成绩": [90888095],
        "年龄": [23192033],
        "身高": [175165170173],
        "体重": [71.550.566.575.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__':
    # data_res 参考准备数据,此处省略....
    # 使用head和tail获取头尾数据
    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[32])
    
    
"""
------ 第一行: ------
     成绩  年龄   身高    体重  城市
小明  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 pd

if __name__ == '__main__':
    # data_res 参考准备数据,此处省略....

    # 根据标签变更
    print("#-------------- 修改具体值 -------------------")
    print("标签赋值--变更前小英年龄:", data_res.at["小英""年龄"])
    data_res.at["小英""年龄"] = 18
    print("标签赋值--变更后小英年龄:", data_res.at["小英""年龄"])
    # 根据位置变更
    print("位置赋值--变更前小英年龄:", data_res.iat[11])
    data_res.iat[11] = 24
    print("位置赋值--变更后小英年龄:", data_res.iat[11])

    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 pd

if __name__ == '__main__':
    # data_res 参考准备数据,此处省略....

    # 增加一列
    data_res["爱好"] = ["旅游""游戏""篮球""学习"]
    print("------------------ 增加一列: ------------------ n ", data_res)
    # 删除一列
    new_data = data_res.drop(["城市""成绩""体重"], axis=1)
    print("------------------drop 删除多列: ------------------ n ", new_data)

    # 使用pd.concat连接两个dataframe
    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)

    # 使用drop也可以删除行
    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: 用于删除行或列的函数。它可以在 DataFrameSeries 上使用,用于删除指定的行或列,并返回一个新的对象,原始对象保持不变。axis 参数用于指定是删除行还是列,其中 axis=0 表示行,axis=1 表示列。默认情况下,axis=0
  • concat: 将数据沿着某个轴进行拼接,可以按行拼接(垂直拼接)或按列拼接(水平拼接),使用参数axis 指定拼接的轴,axis=0 表示按行拼接(垂直拼接),axis=1 表示按列拼接(水平拼接),默认是按照行拼接

3.5 排序数据

import pandas as pd

if __name__ == '__main__':
    # data_res 参考准备数据,此处省略....
    # 根据年龄排序
    by_age_asc = data_res.sort_values(by="年龄", ascending=True)
    print("-------------------- 根据年龄升序排序(原始数据不变) --------------------:n", by_age_asc)
    # 根据成绩降序排序,inplace=True会修改原始数据
    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排序,返回当前数据在所属列的排名名次
    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 函数用于排序 DataFrameSeries ,具体参数如下:

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 pd

if __name__ == '__main__':
    # 创建DataFrame
    data_dict = {
        "水果": ["香蕉""苹果""葡萄""橘子"],
        "进货价": [1.250.563.51.15],
        "最低价": [1.550.804.02.00],
        "最高价": [3.451.56.54.15],
        "数量": [600500400500],
    }
    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 pd

if __name__ == '__main__':
    # 创建DataFrame
    data_dict = {
        "水果": ["香蕉""苹果""葡萄""橘子"],
        "进货价": [1.250.563.51.15],
        "最低价": [1.550.804.02.00],
        "最高价": [3.451.56.54.15],
        "数量": [600500400500],
    }
    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 random
import pandas as pd


def custom_compute(x: pd.Series):
    """
    变更指定列信息
    :param x:
    :return:
    """

    # 这里接受的是Series
    if x.name == "最低价":
        return x + random.randint(1100) / 100
    elif x.name == "数量":
        return x * 1.5
    return x


def total_cost(x: pd.Series):
    """
    计算总成本
    :param x:
    :return:
    """

    money = x["进货价"] * x["数量"]
    print("{} 进货价:{} 数量:{} 成本:{}".format(x["水果"], x["进货价"], x["数量"], money))
    return money


if __name__ == '__main__':
    # 创建DataFrame
    data_dict = {
        "水果": ["香蕉""苹果""葡萄""橘子"],
        "进货价": [1.250.563.51.15],
        "最低价": [1.550.804.02.00],
        "最高价": [3.451.56.54.15],
        "数量": [600500400500],
    }
    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 random

import pandas as pd

if __name__ == '__main__':
    # 创建DataFrame 科目
    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(60100for _ 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
"""
    


Python库学习(十一):数据分析Pandas[上篇]
Python库学习(十一):数据分析Pandas[上篇]
微信搜一搜
 码记
“阅读原文”我们一起进步


原文始发于微信公众号(猿码记):Python库学习(十一):数据分析Pandas[上篇]

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/186107.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!