• Pandas:强大的Python数据分析工具包


    Pandas:强大的Python数据分析工具包

    pandas是一个Python包,提供快速,灵活和富有表现力的数据结构,旨在既简单又直观的处理“关系”或“标记”数据。它旨在成为在Python中进行实际,真实世界数据分析的基本高级构建块。
    pandas是一个开源的,BSD许可的库,为Python编程语言提供高性能,易于使用的数据结构和数据分析工具。

    以下是pandas擅长的几件事:

    • 轻松处理浮点和非浮点数据中的缺失数据(表示为 NaN、NA 或 NaT)
    • 大小可变性:可以在DataFrame和更高维度的对象中插入和删除列
    • 自动和显式数据对齐:对象可以显式对齐到一组标签,或者用户可以简单地忽略标签,让Series、DataFrame等在计算中自动对齐数据
    • 强大、灵活的按功能分组group by,可对数据集执行拆分-应用-合并操作,用于聚合和转换数据
    • 可以将其他 Python 和 NumPy 数据结构中不规则、索引不同的数据轻松转换为DataFrame对象
    • 基于标签的智能进行切片花式索引子集
    • 直观的合并联接数据集
    • 数据集的灵活重塑reshaping透视pivoting
    • 轴的分层Hierarchical标签(每个刻度可能有多个标签)
    • 强大的 IO 工具,用于从平面文件(CSV 和分隔文件)、Excel 文件、数据库加载数据,以及从超快 HDF5 格式保存/加载数据
    • 特定于时间序列time sequence的功能:日期范围生成和频率转换、移动窗口统计信息、日期偏移和滞后(date shifting and lagging)

    1. 对象创建

    • 通过传递值列表来创建Series,让 pandas 创建默认整数索引
    • 使用Numpy及date_range日期Series创建DataFrame
    • 通过传递可转换为类似Serial结构的对象字典来创建DataFrame

    2. 查看数据

    • DataFrame.head() and DataFrame.tail() 查看前几行,末尾几行

    • DataFrame.index or DataFrame.columns 查看行索引,列标签

    • DataFrame.to_numpy()给出了基础数据的NumPy表示形式,在输出中不包括索引或列标签;当DataFrame具有不同数据类型的列时,这可能是一项代价高昂的操作,

    • 这归结为Pandas和NumPy之间的根本区别:NumPy数组在整个数组中具有一个dtype,而pandasDataFrame每列具有一个dtype。

    • 当调用DataFrame.to_numpy()时,Pandas会找到可以容纳DataFrame中所有dtype的NumPy dtype。这可能最终成为对象需要将每个值转换为Python对象。

    • describe()显式数据的快速统计摘要:count、mean、std、min、25%、50%、75%、max

    • df.T转置数据,行列互换

    • DataFrame.sort_index()按轴排序:

    • DataFrame.sort_values()按值排序:

    • 对于 df,所有浮点值和DataFrame.to_numpy()的DataFrame速度很快,不需要复制数据

    • 对于 df2,具有多个 dtype 的DataFrame,DataFrame.to_numpy() 相对昂贵

    3. 选择数据

    3.1 获取行列

    • 获取列:选择单个列,这将生成一个Series,等效于 df.A
    • 获取行:切片[] (getitem), df[0:3] 同 df[‘2013-01-01’:‘2022-01-03’]

    3.2 根据标签获取(根据标签/下标位置获取,差别在于标签前闭后闭,位置前闭后开)

    • 建议使用优化的Pandas数据访问方法,DataFrame.at(),DataFrame.iat(),DataFrame.loc() 和 DataFrame.iloc()。

    • DataFrame.loc() or DataFrame.at()

    • 标签获取单行全列,在多轴上按标签选取多行可选列,标签切片多行可选列,单行单列

    • 获取标量值,快速获取标量值

    • 获取标量
      print(df.loc[dates[0], “A”])

    • 快速获取标量,同上
      print(df.at[dates[0], “A”])

    3.3 按下标位置获取(根据标签/下标位置获取,差别在于标签前闭后闭,位置前闭后开)

    • DataFrame.iloc() or DataFrame.at()

    • 按传递的整数,行列数组切片类似Numpy/Phthon,Numpy/Phthon类型的传递多个值list

    • 显式切片行,显式切片列

    • 显式获取值/快速获取

    • 获取标量
      print(df.iloc[1, 1])

    • 快速访问标量,同上
      df.iat[1, 1]

    3.4 布尔索引

    • 使用单个列的值来选择数据

    • 从满足布尔条件的DataFrame中选择值(其他不满足的返回NaN)

    • 使用isin()进行过滤

    • 使用isin()进行过滤

    3.5 设置

    • 设置新列会自动按索引对齐数据

    • 通过标签及列设置值/通过下标位置设置值

    • 通过NumPy array设置值

    • 通过where条件设置值

    • 通过标签及列设置值/通过下标位置设置值

    • 通过NumPy array设置值

    • 通过where条件设置值

    4. 丢失数据

    • Pandas主要使用值np.nan来表示缺失的数据。默认情况下,它不包含在计算中。

    • reindex重新编制索引允许更改/添加/删除指定轴上的索引。这将返回数据的副本

    • DataFrame.dropna() 丢弃有数据缺失的行

    • DataFrame.fillna(value=5) 过滤出Nan的数据并赋值5

    • isna() 获取NaN的布尔mask,为NaN返回True,否则False

    • DataFrame.fillna(value=5) 过滤出Nan的数据并赋值5

    • isna() 获取NaN的布尔mask,为NaN返回True,否则False

    5. 运算符

    • 统计操作通常会排除丢失的数据。NaN与任何数运算得到NaN

    • 执行描述性统计:df.mean()求均值

    • 操作具有不同维度且需要对齐的对象。此外,Pandas会自动沿指定尺寸广播:

    • 操作具有不同维度且需要对齐的对象。此外,Pandas会自动沿指定尺寸广播

    • DataFrame.apply() 对数据应用一个用户定义的方法

    • 直方图和离散化(Histogramming and Discretization)

    • 字符串方法

    • 在str属性中配备了一组字符串处理方法,这些方法使对数组的每个元素进行操作变得容易,模式匹配通常默认使用正则表达式

    6. 合并

    • pandas提供了各种工具,可以在连接/合并类型操作的情况下,轻松地将Series和DataFrame对象与索引和关系代数功能的各种设置逻辑组合在一起。
    • concat():将Pandas对象沿着一个轴连接在一起
    • merge() 允许数据库join类型的合并,将多列结果组合
    • 切片
    • 将列映射到DataFrame相对较快。但是添加行需要副本,并且可能很昂贵。建议将预先构建的记录列表传递给DataFrame构造函数,而不是通过迭代向其追加记录来生成DataFrame;
    • merge() 允许数据库join类型的合并,将多列结果组合

    7. 分组group

    • "group by"指的是涉及以下一个或多个步骤的过程(Splitting Applying Combining):根据某些条件将数据拆分为多个组、将函数独立应用于每个组、将结果合并到数据结构中
    • 按多个列分组形成一个分层索引,再次应用 sum()

    8. 分层索引和重塑(Hierarchical Indexing and Reshaping)

    • stack() 方法“压缩”DataFrame列中的级别
    • Pivot tables数据透视表
    • pivot_table() 透视DataFrame,指定值、索引和列
    • 对于“stack”DataFrame或Series(以 MultiIndex 作为索引),stack() 的反运算是 unstack(),默认情况下,它取消堆叠最后一个级别
    • Pivot tables数据透视表
    • pivot_table() 透视DataFrame,指定值、索引和列

    9. 时间Series

    • pandas具有简单,强大且高效的功能,用于在频率转换期间执行重采样操作(例如,将第二次数据转换为5分钟数据)

    • Series.tz_localize() 将时间Series本地化为时区

    • Series.tz_convert() 将识别时区的时间Series转换为另一个时区

    • 在Period和时间戳之间进行转换可以使用一些方便的算术函数。

    • Series.tz_localize() 将时间Series本地化为时区

    • Series.tz_convert() 将识别时区的时间Series转换为另一个时区

    • 在时间跨度表示之间转换

    • 在Period和时间戳之间进行转换可以使用一些方便的算术函数。在以下示例中将年度结束于 11 月的季度频率转换为季度结束后月底的上午 9 点:

    10. 分类数据Categoricals

    • 可以在DataFrame中包含分类数据
    • 转换raw_grade为category数据类型
    • 重命名类别名称
    • 重新排序类别并同时添加缺少的类别(默认情况下,Series.cat()下的方法将返回一个新的系列)
    • 排序是按类别中的顺序排序的,而不是词法顺序
    • 按分类列分组也会显示空类别

    11. Plotting绘图调用matplotlib

    Matplot pyplot绘制单图,多子图不同样式详解,这一篇就够了

    Matplotlib三维绘图,这一篇就够了

    • plt.close()关闭图片窗口
    • 在DataFrame上,plot()方法便于绘制带有标签的所有列:

    12. 导入/导出数据

    • DataFrame.to_csv() 写入csv
    • pd.read_csv() 读取csv
    • DataFrame.to_hdf() 写入hdf5
    • pd.read_hdf(“foo.h5”, “df”) 读取hdf5
    • DataFrame.to_excel() 写入excel,设置sheet名字
    • pd.read_excel() 读取excel,可设置读取的sheet名字

    源码

    import numpy as np
    
    import pandas as pd
    
    # 1. 对象创建
    # 通过传递值列表来创建Series,让 pandas 创建默认整数索引
    s = pd.Series([1, 3, 5, np.nan, 6, 8])
    print(s)
    
    # 使用Numpy及date_range日期Series创建DataFrame
    dates = pd.date_range("20130101", periods=6)
    print(dates)
    df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list("ABCD"))
    print(df)
    
    # 通过传递可转换为类似Serial结构的对象字典来创建DataFrame
    df2 = pd.DataFrame(
        {
            "A": 1.0,
            "B": pd.Timestamp("20130102"),
            "C": pd.Series(1, index=list(range(4)), dtype="float32"),
            "D": np.array([3] * 4, dtype="int32"),
            "E": pd.Categorical(["test", "train", "test", "train"]),
            "F": "foo",
        }
    )
    print(df2)
    print(df2.dtypes)  # 列的类型
    
    # 2. 查看数据
    # DataFrame.head() and DataFrame.tail() 查看前几行,末尾几行
    # DataFrame.index or DataFrame.columns 查看行索引,列标签
    # DataFrame.to_numpy()给出了基础数据的NumPy表示形式,在输出中不包括索引或列标签;当DataFrame具有不同数据类型的列时,这可能是一项代价高昂的操作,
    # 这归结为Pandas和NumPy之间的根本区别:NumPy数组在整个数组中具有一个dtype,而pandasDataFrame每列具有一个dtype。
    # 当调用DataFrame.to_numpy()时,Pandas会找到可以容纳DataFrame中所有dtype的NumPy dtype。这可能最终成为对象需要将每个值转换为Python对象。
    # describe()显式数据的快速统计摘要:count、mean、std、min、25%、50%、75%、max
    # df.T转置数据,行列互换
    # DataFrame.sort_index()按轴排序:
    # DataFrame.sort_values()按值排序:
    print(df.head(2))
    print(df.tail(3))
    print(df.index)
    print(df.columns)
    
    # 对于 df,所有浮点值和DataFrame.to_numpy()的DataFrame速度很快,不需要复制数据
    # 对于 df2,具有多个 dtype 的DataFrame,DataFrame.to_numpy() 相对昂贵
    print(df.to_numpy())
    print(df2.to_numpy())
    
    print(df.describe())
    print(df.T)
    print(df.sort_index(axis=1, ascending=False))
    print(df.sort_values(by="B"))
    
    # 3. 选择数据
    ## 3.1 获取行列
    # 获取列:选择单个列,这将生成一个Series,等效于 df.A
    # 获取行:切片[] (__getitem__), df[0:3] 同 df['2013-01-01':'2022-01-03']
    print(df['A'])
    print(df.A)
    
    print(df[0:3])
    print(df['2013-01-01':'2013-01-03'])
    
    ## 3.2 根据标签获取(根据标签/下标位置获取,差别在于标签前闭后闭,位置前闭后开)
    # 建议使用优化的Pandas数据访问方法,DataFrame.at(),DataFrame.iat(),DataFrame.loc() 和 DataFrame.iloc()。
    # DataFrame.loc() or DataFrame.at()
    # 标签获取单行全列,在多轴上按标签选取多行可选列,标签切片多行可选列,单行单列
    # 获取标量值,快速获取标量值
    print(df.loc[dates[0]])
    
    print(df.loc[:, ["A", "B"]])
    
    print(df.loc["20130102":"20130104", ["A", "B"]])
    
    print(df.loc["20130102", ["A", "B"]])
    
    # 获取标量
    print(df.loc[dates[0], "A"])
    # 快速获取标量,同上
    print(df.at[dates[0], "A"])
    
    ## 3.3 按下标位置获取(根据标签/下标位置获取,差别在于标签前闭后闭,位置前闭后开)
    # DataFrame.iloc() or DataFrame.at()
    # 按传递的整数,行列数组切片类似Numpy/Phthon,Numpy/Phthon类型的传递多个值list
    # 显式切片行,显式切片列
    # 显式获取值/快速获取
    print(df.iloc[3])
    print(df.iloc[3:5, 0:2])
    print(df.iloc[[1, 2, 4], [0, 2]])
    
    print(df.iloc[1:3, :])
    print(df.iloc[:, 1:3])
    
    # 获取标量
    print(df.iloc[1, 1])
    # 快速访问标量,同上
    df.iat[1, 1]
    
    ## 3.4 布尔索引
    # 使用单个列的值来选择数据
    # 从满足布尔条件的DataFrame中选择值(其他不满足的返回NaN)
    # 使用isin()进行过滤
    print(df[df["A"] > 0])
    print(df[df > 0])
    
    # 使用isin()进行过滤
    df2 = df.copy()
    df2["E"] = ["one", "one", "two", "three", "four", "three"]
    print(df2)
    print(df2[df2["E"].isin(["two", "four"])])
    
    ## 3.5 设置
    # 设置新列会自动按索引对齐数据
    # 通过标签及列设置值/通过下标位置设置值
    # 通过NumPy array设置值
    # 通过where条件设置值
    s1 = pd.Series([1, 2, 3, 4, 5, 6], index=pd.date_range("20130102", periods=6))
    print(s1)
    df["F"] = s1
    print(df)
    
    # 通过标签及列设置值/通过下标位置设置值
    df.at[dates[0], "A"] = 0
    df.iat[0, 1] = 0
    
    # 通过NumPy array设置值
    df.loc[:, "D"] = np.array([5] * len(df))
    print(df)
    
    # 通过where条件设置值
    df2 = df.copy()
    df2[df2 > 0] = -df2
    print(df2)
    
    # 4. 丢失数据
    # Pandas主要使用值np.nan来表示缺失的数据。默认情况下,它不包含在计算中。
    # reindex重新编制索引允许更改/添加/删除指定轴上的索引。这将返回数据的副本
    # DataFrame.dropna() 丢弃有数据缺失的行
    # DataFrame.fillna(value=5) 过滤出Nan的数据并赋值5
    # isna() 获取NaN的布尔mask,为NaN返回True,否则False
    df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ["E"])
    df1.loc[dates[0]: dates[1], "E"] = 1
    print(df1)
    
    print(df1.dropna(how="any"))
    
    # DataFrame.fillna(value=5) 过滤出Nan的数据并赋值5
    print(df1.fillna(value=5))
    
    # isna() 获取NaN的布尔mask,为NaN返回True,否则False
    print(pd.isna(df1))
    
    # 5. 运算符
    # 统计操作通常会排除丢失的数据。NaN与任何数运算得到NaN
    # 执行描述性统计:df.mean()求均值
    # 操作具有不同维度且需要对齐的对象。此外,Pandas会自动沿指定尺寸广播:
    print(df.mean())  # 按列
    print(df.mean(1))  # 按行
    
    s = pd.Series([1, 3, 5, np.nan, 6, 8], index=dates).shift(2)
    print(s)
    
    # 操作具有不同维度且需要对齐的对象。此外,Pandas会自动沿指定尺寸广播
    print(df)
    print(df.sub(s, axis="index"))
    
    # DataFrame.apply() 对数据应用一个用户定义的方法
    print(df.apply(np.cumsum))
    print(df.apply(lambda x: x.max() - x.min()))
    
    # 直方图和离散化(Histogramming and Discretization)
    s = pd.Series(np.random.randint(0, 7, size=10))
    print(s)
    print(s.value_counts())
    
    # 字符串方法
    # 在str属性中配备了一组字符串处理方法,这些方法使对数组的每个元素进行操作变得容易,模式匹配通常默认使用正则表达式
    s = pd.Series(["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"])
    print(s.str.lower())
    
    # 5. 合并
    # pandas提供了各种工具,可以在连接/合并类型操作的情况下,轻松地将Series和DataFrame对象与索引和关系代数功能的各种设置逻辑组合在一起。
    # concat():将Pandas对象沿着一个轴连接在一起
    # merge() 允许数据库join类型的合并,将多列结果组合
    df = pd.DataFrame(np.random.randn(10, 4))
    print(df)
    
    # 切片
    pieces = [df[:3], df[3:7], df[7:]]
    print(pd.concat(pieces))
    
    # 将列映射到DataFrame相对较快。但是添加行需要副本,并且可能很昂贵。建议将预先构建的记录列表传递给DataFrame构造函数,而不是通过迭代向其追加记录来生成DataFrame;
    # merge() 允许数据库join类型的合并,将多列结果组合
    left = pd.DataFrame({"key": ["foo", "foo"], "lval": [1, 2]})
    right = pd.DataFrame({"key": ["foo", "foo"], "rval": [4, 5]})
    print(left, right)
    print(pd.merge(left, right, on="key"))
    
    left = pd.DataFrame({"key": ["foo", "bar"], "lval": [1, 2]})
    right = pd.DataFrame({"key": ["foo", "bar"], "rval": [4, 5]})
    print(left, right)
    print(pd.merge(left, right, on="key"))
    
    # 6. 分组group
    # "group by"指的是涉及以下一个或多个步骤的过程(Splitting Applying Combining):根据某些条件将数据拆分为多个组、将函数独立应用于每个组、将结果合并到数据结构中
    df = pd.DataFrame(
        {
            "A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
            "B": ["one", "one", "two", "three", "two", "two", "one", "three"],
            "C": np.random.randn(8),
            "D": np.random.randn(8),
        }
    )
    print(df)
    print(df.groupby("A")[["C", "D"]].sum())
    # 按多个列分组形成一个分层索引,再次应用 sum()
    print(df.groupby(["A", "B"]).sum())
    
    # 7. 分层索引和重塑(Hierarchical Indexing and Reshaping)
    # stack() 方法“压缩”DataFrame列中的级别
    # Pivot tables数据透视表
    # pivot_table() 透视DataFrame,指定值、索引和列
    tuples = list(
        zip(
            ["bar", "bar", "baz", "baz", "foo", "foo", "qux", "qux"],
            ["one", "two", "one", "two", "one", "two", "one", "two"],
        )
    )
    index = pd.MultiIndex.from_tuples(tuples, names=["first", "second"])
    df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=["A", "B"])
    df2 = df[:4]
    print(df2)
    
    stacked = df2.stack()
    print(stacked)
    
    # 对于“stack”DataFrame或Series(以 MultiIndex 作为索引),stack() 的反运算是 unstack(),默认情况下,它取消堆叠最后一个级别
    print(stacked.unstack())
    print(stacked.unstack(1))
    print(stacked.unstack(0))
    
    # Pivot tables数据透视表
    # pivot_table() 透视DataFrame,指定值、索引和列
    df = pd.DataFrame(
        {
            "A": ["one", "one", "two", "three"] * 3,
            "B": ["A", "B", "C"] * 4,
            "C": ["foo", "foo", "foo", "bar", "bar", "bar"] * 2,
            "D": np.random.randn(12),
            "E": np.random.randn(12),
        }
    )
    print(df)
    print(pd.pivot_table(df, values="D", index=["A", "B"], columns=["C"]))  # 透视还是比较复杂的,可以细看这个例子
    
    # 8. 时间Series
    # pandas具有简单,强大且高效的功能,用于在频率转换期间执行重采样操作(例如,将第二次数据转换为5分钟数据)
    # Series.tz_localize() 将时间Series本地化为时区
    # Series.tz_convert() 将识别时区的时间Series转换为另一个时区
    # 在Period和时间戳之间进行转换可以使用一些方便的算术函数。
    rng = pd.date_range("1/1/2012", periods=100, freq="S")
    ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
    print(ts.resample("5Min").sum())
    
    # Series.tz_localize() 将时间Series本地化为时区
    rng = pd.date_range("3/6/2012 00:00", periods=5, freq="D")
    ts = pd.Series(np.random.randn(len(rng)), rng)
    print(ts)
    ts_utc = ts.tz_localize("UTC")
    print(ts_utc)
    
    # Series.tz_convert() 将识别时区的时间Series转换为另一个时区
    print(ts_utc.tz_convert("US/Eastern"))
    
    # 在时间跨度表示之间转换
    rng = pd.date_range("1/1/2012", periods=5, freq="M")
    ts = pd.Series(np.random.randn(len(rng)), index=rng)
    print(ts)
    ps = ts.to_period()  # 年月日(日为月末最后一天)转年月
    print(ps)
    
    print(ps.to_timestamp())  # 转回年月日(日为月初第一天)
    
    # 在Period和时间戳之间进行转换可以使用一些方便的算术函数。在以下示例中将年度结束于 11 月的季度频率转换为季度结束后月底的上午 9 点:
    prng = pd.period_range("1990Q1", "2000Q4", freq="Q-NOV")
    ts = pd.Series(np.random.randn(len(prng)), prng)
    ts.index = (prng.asfreq("M", "e") + 1).asfreq("H", "s") + 9
    print(ts.head())
    
    # 9. 分类数据Categoricals
    # 可以在DataFrame中包含分类数据
    df = pd.DataFrame(
        {"id": [1, 2, 3, 4, 5, 6], "raw_grade": ["a", "b", "b", "a", "a", "e"]}
    )
    # 转换raw_grade为category数据类型
    df["grade"] = df["raw_grade"].astype("category")
    print(df["grade"])
    
    # 重命名类别名称
    new_categories = ["very good", "good", "very bad"]
    df["grade"] = df["grade"].cat.rename_categories(new_categories)
    
    # 重新排序类别并同时添加缺少的类别(默认情况下,Series.cat()下的方法将返回一个新的系列)
    df["grade"] = df["grade"].cat.set_categories(
        ["very bad", "bad", "medium", "good", "very good"]
    )
    print(df["grade"])
    
    # 排序是按类别中的顺序排序的,而不是词法顺序
    print(df.sort_values(by="grade"))
    
    # 按分类列分组也会显示空类别
    print(df.groupby("grade").size())
    
    # 10. Plotting绘图
    # plt.close()关闭图片窗口
    # 在DataFrame上,plot()方法便于绘制带有标签的所有列:
    import matplotlib.pyplot as plt
    plt.close("all")
    
    ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))
    ts = ts.cumsum()
    ts.plot()
    plt.show()
    
    df = pd.DataFrame(
        np.random.randn(1000, 4), index=ts.index, columns=["A", "B", "C", "D"]
    )
    df = df.cumsum()
    plt.figure()
    df.plot()
    plt.legend(loc='best')
    plt.show()
    
    # 11. 导入/导出数据
    # DataFrame.to_csv() 写入csv
    # pd.read_csv() 读取csv
    # DataFrame.to_hdf() 写入hdf5
    # pd.read_hdf("foo.h5", "df") 读取hdf5
    # DataFrame.to_excel() 写入excel,设置sheet名字
    # pd.read_excel() 读取excel,可设置读取的sheet名字
    
    df.to_csv("foo.csv")
    print(pd.read_csv("foo.csv"))
    
    df.to_hdf("foo.h5", "df")
    print(pd.read_hdf("foo.h5", "df"))
    
    df.to_excel("foo.xlsx", sheet_name="Sheet1")
    print(pd.read_excel("foo.xlsx", "Sheet1", index_col=None, na_values=["NA"]))
    
    • 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
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351

    参考

  • 相关阅读:
    Leetcode array 704 27 189 121 380 238 134 13
    密码技术 (5) - 数字签名
    ArcgisForJS如何使用ArcGIS Server的缓冲区几何服务?
    算法设计与分析-8593 最大覆盖问题
    springbooy+求职招聘网站 毕业设计-附源码301914
    Java8 新特性之Stream(二)-- Stream的中间操作
    Linux输出重定向 >> 文件 2>&1
    SpringMVC——进阶
    7 矩阵中战斗力最弱的 K 行
    七天学会C语言-第一天(C语言基本语句)
  • 原文地址:https://blog.csdn.net/qq_40985985/article/details/127547381