• 《对比Excel,轻松学习Python数据分析》读书笔记------数据运算


    8 数据运算

    8.1 算术运算

    Excel

    基本的公式运用

    =算术运算对象 算术运算符(+ - * /) 算术运算对象
    
    • 1

    Python

    Series对象可以直接通过算术符进行加减乘除等运算,返回一个新的Series对象

    df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
    
    # 两列相加
    print(df["A"] + df["B"])
    """
    0    5
    1    7
    2    9
    dtype: int64
    """
    # 两列相减
    print(df["A"] - df["B"])
    """
    0   -3
    1   -3
    2   -3
    dtype: int64
    """
    
    #两列相乘
    print(df["A"] * df["B"])
    """
    0     4
    1    10
    2    18
    dtype: int64
    """
    
    #两列相除
    print(df["A"] / df["B"])
    """
    0    0.25
    1    0.40
    2    0.50
    dtype: float64
    """
    
    # 列的每个元素+1
    print(df["A"] + 1)
    """
    0    2
    1    3
    2    4
    Name: A, dtype: int64
    """
    
    # 列的每个元素-1
    print(df["A"] - 1)
    """
    0    0
    1    1
    2    2
    Name: A, dtype: int64
    """
    
    #列的每个元素乘2
    print(df["A"] * 2)
    """
    0    2
    1    4
    2    6
    Name: A, dtype: int64
    """
    
    #列的每个元素除2
    print(df["A"] / 2)
    """
    0    0.5
    1    1.0
    2    1.5
    Name: A, dtype: float64
    """
    
    • 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
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    8.2 比较运算

    Excel

    基本的公式运用

    =比较运算对象 比较运算符(> = < >= <= <>[不等于]) 比较运算对象
    
    • 1

    Python

    Series对象可以直接通过比较符(> == < >= <= !=)进行比较运算,返回一个新的Series对象,由比较的结果(TrueFalse)组成。

    df = pd.DataFrame({"A": [1, 3, 4], "B": [2, 3, 5]})
    print(df["A"] < df["B"])
    """
    0     True
    1    False
    2     True
    dtype: bool
    """
    
    print(df["A"] == df["B"])
    """
    0    False
    1     True
    2    False
    dtype: bool
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    8.3 汇总运算

    8.3.1 计算总个数count

    Excel

    =COUNTA(区域)   # 计算指定区域内的非空单元格总数
    =COUNT(区域)	  # 计算指定区域的数值型数据个数
    
    • 1
    • 2

    Python

    df.count(axis: 'Axis' = 0,
             numeric_only: 'bool' = False)
    
    • 1
    • 2
    • axis设置把行(0"index")计数还是把列(1"columns")计数
    • numeric_only设置只计算数值型数据行/列(int,float,bool)。
    • 返回值为一个由行名(axis=1)或列名(axis=0)作索引,各列/行的非空值组成的Series对象,

    如:

    df = pd.DataFrame({
        "A": [1, 3, 4, 5, 5, 6],
        "B": [2, 3, 5, None, None, 2],
        "C": ["hello", "world", 1, 2, 3, None]
    },index=["一","二","三","四","五","六"])
    
    result = df.count()
    print(result)
    """
    A    6
    B    4
    C    5
    dtype: int64
    """
    
    result = df.count(axis=1)
    print(result)
    """
    一    3
    二    3
    三    3
    四    2
    五    2
    六    2
    dtype: int64
    """
    
    result = df.count(numeric_only=True)
    print(result)
    """
    A    6
    B    4
    dtype: int64
    """
    
    • 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
    Series.count()
    
    • 1
    • 返回该Series对象中的非空值总个数

    如:

    n = df["B"].count()
    print(n)
    # 4
    
    • 1
    • 2
    • 3

    8.3.2 计算总和sum

    Excel

    =SUM(区域)
    
    • 1

    Python

    df.sum(axis=None,
           skipna=True,
           numeric_only=None,
           min_count=0)
    
    • 1
    • 2
    • 3
    • 4
    • axis设置把行(0"index")求和还是把列(1"columns")求和
    • skipna设置忽略空值
    • numeric_only设置只计算数值型数据行/列(int,float,bool)。
    • min_count设置最低求和数个数。如何本列/行的数值型数据个数小于该最低求和数个数,将不会进行求和运算。
    • 返回值为一个由行名(axis=1)或列名(axis=0)作索引,各列/行的数据总和组成的Series对象,

    如:

    df = pd.DataFrame(
        {
            "A": [1, 3, 4, 5, 5, 6],
            "B": [2, 3, 5, 19, 20, 2],
            "C": [12, 3, None, None, None, None]
        },
        index=["一", "二", "三", "四", "五", "六"])
    
    print(df.sum())
    """
    A    24.0
    B    51.0
    C    15.0
    dtype: float64
    """
    print(df.sum(axis=1))
    """
    一    15.0
    二     9.0
    三     9.0
    四    24.0
    五    25.0
    六     8.0
    dtype: float64
    """
    print(df.sum(min_count=3))
    """
    A    24.0
    B    51.0
    C     NaN
    dtype: float64
    """
    
    • 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
    Series.sum()
    
    • 1
    • 返回该Series对象的数据的总和

    如:

    s = df["B"].sum()
    print(s)
    # 51
    
    • 1
    • 2
    • 3

    8.3.3 计算算术平均数mean

    算 术 平 均 数 : m e a n ( A n ) = a 1 + a 2 + ⋅ ⋅ ⋅ + a n n = 1 n ∑ i = 1 n a i 算术平均数:mean(A_n)=\frac{a_1+a_2+···+a_n}{n}=\frac{1}{n}\sum_{i=1}^{n}a_i \\ :mean(An)=na1+a2++an=n1i=1nai

    Excel

    =AVGERAGE(区域)
    
    • 1

    Python

    参数和返回值类似sum()

    df.mean(axis: 'int | None | lib.NoDefault' = <no_default>,
            skipna=True,
            numeric_only=None)
    
    • 1
    • 2
    • 3
    Series.mean()
    
    • 1

    如:

    df = pd.DataFrame(
        {
            "A": [1, 3, 4, 5, 5, 6],
            "B": [2, 3, 5, 19, 20, 2],
            "C": [12, 3, None, None, None, None]
        },
        index=["一", "二", "三", "四", "五", "六"])
    
    print(df.mean())
    """
    A    4.0
    B    8.5
    C    7.5
    dtype: float64
    """
    
    print(df.mean(axis=1))
    """
    一     5.0
    二     3.0
    三     4.5
    四    12.0
    五    12.5
    六     4.0
    dtype: float64
    """
    
    print(df["B"].mean())
    # 8.5
    
    • 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

    8.3.4 计算最值max min

    Excel

    =MAX(区域)
    =MIN(区域)
    
    • 1
    • 2

    Python

    参数和返回值类似sum()

    df.max(axis: 'int | None | lib.NoDefault' = <no_default>,
           skipna=True,
           numeric_only=None)
    
    df.min(axis: 'int | None | lib.NoDefault' = <no_default>,
           skipna=True,
           numeric_only=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    Series.max()
    Series.min()
    
    • 1
    • 2

    如:

    df = pd.DataFrame(
        {
            "A": [1, 3, 4, 5, 5, 6],
            "B": [2, 3, 5, 19, 20, 2],
            "C": [12, 3, None, None, None, None]
        },
        index=["一", "二", "三", "四", "五", "六"])
    
    print(df.max())
    """
    A     6.0
    B    20.0
    C    12.0
    dtype: float64
    """
    print(df.min(axis=1))
    """
    一    1.0
    二    3.0
    三    4.0
    四    5.0
    五    5.0
    六    2.0
    dtype: float64
    """
    print(df["B"].max())
    # 20
    
    • 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

    8.3.5 计算中位数median

    中 位 数 : 将 数 据 从 小 到 大 排 列 , 位 于 正 中 间 的 一 个 数 据 或 两 个 数 据 的 平 均 值 m e d i a n   ( A 2 k ) = a k + a k + 1 2 m e d i a n   ( A 2 k + 1 ) = a k + 1 其 中 , a k ≤ a k + 1 , k = 1 , 2 , 3 ⋅ ⋅ ⋅ 中位数:将数据从小到大排列,位于正中间的一个数据或两个数据的平均值\\ median \ (A_{2k})=\frac{a_k+a_{k+1}}{2} \\ median \ (A_{2k+1})=a_{k+1}\\ 其中,a_k\le a_{k+1},k=1,2,3··· :median (A2k)=2ak+ak+1median (A2k+1)=ak+1,akak+1,k=1,23

    Excel

    =MEDIAN(区域)
    
    • 1

    Python

    参数和返回值类似sum()

    df.median(axis: 'int | None | lib.NoDefault' = <no_default>,
           skipna=True,
           numeric_only=None)
    
    • 1
    • 2
    • 3
    Series.sum()
    
    • 1

    如:

    df = pd.DataFrame(
        {
            "A": [1, 3, 4, 5, 5, 6],
            "B": [2, 3, 5, 19, 20, 2],
            "C": [12, 3, None, None, None, None]
        },
        index=["一", "二", "三", "四", "五", "六"])
    
    print(df.median())
    """
    A    4.5
    B    4.0
    C    7.5
    dtype: float64
    """
    print(df.median(axis=1))
    """
    一     2.0
    二     3.0
    三     4.5
    四    12.0
    五    12.5
    六     4.0
    dtype: float64
    """
    print(df["B"].median())
    # 4
    
    • 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

    8.3.6 计算众数mode

    众 数 : 一 定 区 域 的 数 据 中 出 现 次 数 最 多 的 数 据 值 众数:一定区域的数据中出现次数最多的数据值 :

    Excel

    =MODE(区域)
    
    • 1

    Python

    参数类似sum()

    df.mode(axis: 'Axis' = 0,
            numeric_only: 'bool' = False,
            dropna: 'bool' = True)
    
    • 1
    • 2
    • 3
    Series.mode()
    
    • 1
    • 众数可能会有多个的情况。故返回值为DataFrameSeries

    如:

    df = pd.DataFrame(
        {
            "A": [1, 3, 4, 5, 5, 6],
            "B": [2, 3, 5, 19, 20, 2],
            "C": [12, 3, None, None, None, None]
        },
        index=["一", "二", "三", "四", "五", "六"])
    
    print(df.mode())   # C列3和12出现次数最多且相等
    """
         A    B     C
    0  5.0  2.0   3.0
    1  NaN  NaN  12.0
    """
    
    print(df.mode(axis=1))
    """
         0     1     2
    一  1.0   2.0  12.0
    二  3.0   NaN   NaN
    三  4.0   5.0   NaN
    四  5.0  19.0   NaN
    五  5.0  20.0   NaN
    六  2.0   6.0   NaN
    """
    print(df["B"].mode())
    """
    0    2
    Name: B, dtype: int64
    """
    
    • 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

    8.3.7 计算方差 var

    v a r ( A n ) = 1 n [ ( a 1 − a ˉ ) 2 + ( a 2 − a ˉ ) 2 + ⋅ ⋅ ⋅ + ( a n − a ˉ ) 2 ] = 1 n ∑ i = 1 n ( a i − a ˉ ) 2 其 中 , a ˉ 为 数 据 集 A n 的 平 均 值 var (A_n)=\frac{1}{n}[(a_1-\bar a)^2+(a_2-\bar a)^2+···+(a_n-\bar a)^2]=\frac{1}{n}\sum_{i=1}^{n}(a_i-\bar a)^2\\ 其中,\bar a为数据集A_n的平均值 var(An)=n1[(a1aˉ)2+(a2aˉ)2++(anaˉ)2]=n1i=1n(aiaˉ)2,aˉAn

    Excel

    =VAR(区域)
    
    • 1

    Python

    参数和返回值类似sum()

    df.var(axis: 'Axis' = 0,
           numeric_only: 'bool' = False,
           dropna: 'bool' = True)
    
    • 1
    • 2
    • 3
    Series.var()
    
    • 1

    如:

    df = pd.DataFrame(
        {
            "A": [1, 3, 4, 5, 5, 6],
            "B": [2, 3, 5, 19, 20, 2],
            "C": [12, 3, None, None, None, None]
        },
        index=["一", "二", "三", "四", "五", "六"])
    
    print(df.var())
    """
    A     3.2
    B    73.9
    C    40.5
    dtype: float64
    """
    print(df.var(axis=1))
    """
    一     37.0
    二      0.0
    三      0.5
    四     98.0
    五    112.5
    六      8.0
    dtype: float64
    """
    print(df["B"].var())
    # 73.9
    
    • 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

    8.3.8 计算标准差std

    s t d ( A n ) = v a r ( A n ) = 1 n ∑ i = 1 n ( a i − a ˉ ) 2 std(A_n)=\sqrt {var(A_n)}=\sqrt {\frac{1}{n}\sum_{i=1}^{n}(a_i-\bar a)^2} std(An)=var(An) =n1i=1n(aiaˉ)2

    Excel

    =STDEVP(区域)
    
    • 1

    Python

    参数和返回值类似sum()

    df.std(axis: 'Axis' = 0,
           numeric_only: 'bool' = False,
           dropna: 'bool' = True)
    
    • 1
    • 2
    • 3
    Series.std()
    
    • 1

    如:

    df = pd.DataFrame(
        {
            "A": [1, 3, 4, 5, 5, 6],
            "B": [2, 3, 5, 19, 20, 2],
            "C": [12, 3, None, None, None, None]
        },
        index=["一", "二", "三", "四", "五", "六"])
    
    print(df.std())
    """
    A    1.788854
    B    8.596511
    C    6.363961
    dtype: float64
    """
    print(df.std(axis=1))
    """
    一     6.082763
    二     0.000000
    三     0.707107
    四     9.899495
    五    10.606602
    六     2.828427
    dtype: float64
    """
    print(df["B"].std())
    """
    8.596510920134982
    """
    
    • 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

    8.3.9 计算分位数quantile

    q 分 位 数 : 将 n 个 数 据 按 从 小 到 大 的 顺 序 排 列 , 位 于   1 + ( n − 1 ) ⋅ q   位 置 的 数 据 其 中 0 < q < 1 q分位数:将n个数据按从小到大的顺序排列,位于\ 1+(n-1)·q\ 位置的数据\\ 其中0q:n 1+(n1)q 0<q<1

    在这里插入图片描述

    Excel

    =PERCENTILE(区域,q)
    
    • 1

    Python

    df.quantile(q=0.5,
                axis: 'Axis' = 0,
                numeric_only: 'bool' = True,
                interpolation: 'str' = 'linear')
    
    • 1
    • 2
    • 3
    • 4
    Series.quantile(q=0.5,interpolation: 'str' = 'linear')
    
    • 1
    • q设置分位数。默认0.5,即中位数。也可以是列表。
    • interpolation设置插值方式。假设 j = 1 + ( n − 1 ) ⋅ q    ,   i < j < i + 1 j=1+(n-1)·q\ \ ,\ i< jj=1+(n1)q  , i<j<i+1
      • linear:取 a i + ( j − i ) ( a i + 1 − a i ) a_i+(j-i)(a_{i+1}-a_i) ai+(ji)(ai+1ai)
        • lower:取 a i a_i ai
        • higher:取 a i + 1 a_{i+1} ai+1
        • nearest:令 i , i + 1 i,i+1 i,i+1中离 j j j 较近者为 k k k,取 a k a_k ak
        • midpoint:取 a i + a i + 1 2 \displaystyle \frac{a_i+a_{i+1}}{2} 2ai+ai+1

    如:

    df = pd.DataFrame(
        {
            "A": [1, 3, 4, 5, 5, 6],
            "B": [2, 3, 5, 19, 20, 2],
            "C": [12, 3, None, None, None, None]
        },
        index=["一", "二", "三", "四", "五", "六"])
    
    qdf=df.quantile([0.25,0.5,0.75])
    print(qdf)
    """
             A      B     C
    0.25  3.25   2.25  5.25
    0.50  4.50   4.00  7.50
    0.75  5.00  15.50  9.75
    """
    
    qdf=df.quantile([0.25,0.5,0.75],interpolation="higher")
    print(qdf)
    """
          A   B     C
    0.25  4   3  12.0
    0.50  5   5  12.0
    0.75  5  19  12.0
    """
    
    print(df["A"].quantile(0.25))
    # 3.25
    
    • 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

    8.3.10 计算协方差cov

    c o v [ X n , Y n ] = ∑ i = 1 n ( x i − x ˉ ) ( y i − y ˉ ) n c o v 为 正 表 示 两 列 数 据 正 相 关 。 为 负 代 表 负 相 关 。 cov[X_n,Y_n]=\frac{\sum_{i=1}^{n}(x_i-\bar x)(y_i-\bar y)}{n}\\ cov为正表示两列数据正相关。为负代表负相关。 cov[Xn,Yn]=ni=1n(xixˉ)(yiyˉ)cov

    Excel

    =COVAR(列1,列2)
    
    • 1

    Python

    df.cov()
    
    • 1
    • 返回各列之间的协方差组成的DataFrame
    Series.cov(other)
    
    • 1
    • other为另一个Series对象。
    • 返回两个Series的协方差数值

    如:

    df = pd.DataFrame(
        {
            "A": [1, 3, 4, 5, 5, 6],
            "B": [2, 3, 5, 19, 20, 2],
            "C": [12, 3, None, None, None, None]
        },
        index=["一", "二", "三", "四", "五", "六"])
    print(df.cov())
    """
         A    B          C
    A  3.5 -3.5   7.400000
    B -3.5  3.5  -7.400000
    C  7.4 -7.4  41.866667
    """
    
    c=df["A"].cov(df["B"])
    print(c)
    """
    -3.5
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    8.3.11 计算相关系数correl

    最常见的是皮尔森相关系数:
    c o r r e l ( X n , Y n ) = c o v [ X n , Y n ] v a r ( X n ) ⋅ v a r ( Y n ) = ∑ i = 1 n ( x i − x ˉ ) ( y i − y ˉ ) ∑ i = 1 n ( x i − x ˉ ) 2 ⋅ ∑ i = 1 n ( y i − y ˉ ) 2 c o r r e l 绝 对 值 越 小 说 明 相 关 性 越 弱 。 正 负 代 表 正 负 相 关 。 − 1 ≤ c o r r e l ≤ 1 correl(X_n,Y_n)=\frac{cov[X_n,Y_n]}{\sqrt {var(X_n)·var(Y_n)}}=\frac{\sum_{i=1}^{n}(x_i-\bar x)(y_i-\bar y)}{\sqrt {\sum_{i=1}^n(x_i-\bar x)^2·\sum_{i=1}^n(y_i-\bar y)^2}}\\ correl 绝对值越小说明相关性越弱。正负代表正负相关。-1\le correl \le 1 correl(Xn,Yn)=var(Xn)var(Yn) cov[Xn,Yn]=i=1n(xixˉ)2i=1n(yiyˉ)2 i=1n(xixˉ)(yiyˉ)correl1correl1

    Excel

    =CORREL(列1,列2)
    
    • 1

    Python

    df.corr()
    
    • 1
    • 返回各列之间的相关系数组成的DataFrame
    Series.corr(other)
    
    • 1
    • other为另一个Series对象。
    • 返回两个Series的相关系数

    如:

    df = pd.DataFrame(
        {
            "A": [1, 2, 3, 4, 5, 6],
            "B": [6, 5, 4, 3, 2, 1],
            "C": [12, 1,8, 10, 10, 21]
        },
        index=["一", "二", "三", "四", "五", "六"])
    print(df.corr())
    """
              A         B         C
    A  1.000000 -1.000000  0.611313
    B -1.000000  1.000000 -0.611313
    C  0.611313 -0.611313  1.000000
    """
    r=df["A"].cov(corr["B"])
    print(r)
    # -1.0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    Mac苹果电脑开不了机怎么办,该怎么修复
    JVM类的声明周期
    PyCharm下载安装
    消息队列的实现
    Pod控制器
    网站被篡改的主要方式有几种?
    神经网络logistic回归模型,logistic回归的基本理论
    当一个摆子前端太闲的时候会做什么
    JVM第十六讲:调试排错 - Java 线程分析之线程Dump分析
    【Mysql系列】mysql中删除数据的几种方法
  • 原文地址:https://blog.csdn.net/ncu5509121083/article/details/126183464