您当前的位置: 首页 >  数据结构

IT之一小佬

暂无认证

  • 2浏览

    0关注

    1192博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Pandas数据结构简介

IT之一小佬 发布时间:2022-04-20 09:08:21 ,浏览量:2

首先导入需要的库:

import numpy as np

import pandas as pd
Series

        Series是一个一维标记数组,能够保存任何数据类型(整数、字符串、浮点数、Python 对象等)。轴标签统称为索引。创建系列的基本方法是调用:

s = pd.Series(data, index=index)

在这里,data可以有很多不同的东西:

  • 一个 Python 字典

  • 一个ndarray

  • 标量值(如 5)

传递的索引是轴标签的列表。因此,根据数据是什么,这分为几种情况:

从 ndarray

        如果data是 ndarray,则index必须与data的长度相同。如果没有传递索引,则将创建一个具有 values 的索引。[0, ..., len(data) - 1]

s = pd.Series(np.random.randn(5), index=["a", "b", "c", "d", "e"])
s

s.index

注意:pandas 支持非唯一索引值。如果尝试不支持重复索引值的操作,则此时将引发异常。

从字典

系列可以从 dicts 实例化:

d = {"b": 1, "a": 0, "c": 2}
pd.Series(d)

 注意:

  • 当数据是 dict 并且没有传递Series索引时,如果您使用 Python 版本 >= 3.6 和 pandas 版本 >= 0.23,则索引将按 dict 的插入顺序排序。
  • 如果您使用 Python < 3.6 或 pandas < 0.23,并且未传递索引,则Series索引将是 dict 键的词法排序列表。

        在上面的示例中,如果您使用的是低于 3.6 的 Python 版本或低于 0.23 的 pandas 版本,Series则将按 dict 键的词法顺序(即,而不是)排序。['a', 'b', 'c']['b', 'a', 'c']

如果传递了索引,则将索引中标签对应的数据中的值拉出。

d = {"a": 0.0, "b": 1.0, "c": 2.0}
pd.Series(d, index=["b", "c", "d", "a"])

 注意:NaN(不是数字)是 pandas 中使用的标准缺失数据标记。

从标量值

        如果data是标量值,则必须提供索引。该值将重复以匹配index的长度。

pd.Series(5.0, index=["a", "b", "c", "d", "e"])

 系列类似于 ndarray

    Series行为与 ndarray非常相似,并且是大多数 NumPy 函数的有效参数。但是,切片等操作也会对索引进行切片。

 与 NumPy 数组一样,pandas Series 具有dtype.

        这通常是 NumPy dtype。然而,pandas 和 3rd-party 库在一些地方扩展了 NumPy 的类型系统,在这种情况下,dtype 将是一个ExtensionDtype. pandas 中的一些示例是Categorical data和Nullable integer data type。 

 虽然 Series 类似于 ndarray,但如果您需要实际的ndarray,请使用 Series.to_numpy().

s.to_numpy()

 Series 类似于 dict

Series 就像一个固定大小的 dict,您可以通过索引标签获取和设置值:

 如果不包含标签,则会引发异常:

 使用该get方法,缺少的标签将返回 None 或指定的默认值:

 向量化操作和标签对齐系列

        使用原始 NumPy 数组时,通常不需要逐个值循环。在 pandas 中使用 Series 时也是如此。Series 也可以传递给大多数需要 ndarray 的 NumPy 方法。

         Series 和 ndarray 之间的一个关键区别是 Series 之间的操作会根据标签自动对齐数据。因此,您可以编写计算而不考虑所涉及的系列是否具有相同的标签。

         未对齐系列之间的操作结果将包含所涉及的索引的并集。如果在一个系列或另一个系列中找不到标签,结果将被标记为缺失NaN。无需进行任何明确的数据对齐即可编写代码,这为交互式数据分析和研究提供了极大的自由度和灵活性。pandas 数据结构的集成数据对齐功能使 pandas 有别于大多数用于处理标记数据的相关工具。

注意:通常,我们选择使不同索引对象之间的操作的默认结果产生索引的并集,以避免信息丢失。尽管缺少数据,但具有索引标签通常是作为计算的一部分的重要信息。您当然可以选择通过 dropna函数删除缺少数据的标签。

名称属性

系列也可以有一个name属性:

在许多情况下, Seriesname将自动分配,特别是在获取 DataFrame 的 1D 切片时,如下所示。

您可以使用该pandas.Series.rename()方法重命名系列。

 DataFrame

        DataFrame是一种二维标记数据结构,具有可能不同类型的列。您可以将其视为电子表格或 SQL 表,或 Series 对象的字典。它通常是最常用的 pandas 对象。与 Series 一样,DataFrame 接受许多不同类型的输入:

  • 1D ndarrays、lists、dicts 或 Series 的字典

  • 二维 numpy.ndarray

  • 结构化或记录ndarray

  • 一种Series

  • 其他DataFrame

        除了数据,您还可以选择传递索引(行标签)和 列(列标签)参数。如果您传递索引和/或列,则保证结果 DataFrame 的索引和/或列。因此,Series 的字典加上特定的索引将丢弃所有与传递的索引不匹配的数据。

注意:

  • 如果没有传递轴标签,它们将根据常识规则从输入数据中构造出来。当数据是 dictcolumns且未指定时DataFrame ,如果您使用 Python 版本 >= 3.6 且 pandas >= 0.23,则列将按 dict 的插入顺序排序。
  • 如果您使用的是 Python < 3.6 或 pandas < 0.23,并且columns未指定,则DataFrame列将是字典键的词法排序列表。
来自 Series 或 dicts 的 dict

        结果索引将是各种系列的索引的并集。如果有任何嵌套的 dicts,这些将首先转换为 Series。如果未传递任何列,则这些列将是 dict 键的有序列表。

d = {
    "one": pd.Series([1.0, 2.0, 3.0], index=["a", "b", "c"]),
    "two": pd.Series([1.0, 2.0, 3.0, 4.0], index=["a", "b", "c", "d"]),
}
df = pd.DataFrame(d)
df

pd.DataFrame(d, index=["d", "b", "a"])

pd.DataFrame(d, index=["d", "b", "a"], columns=["two", "three"])

 通过访问index和columns属性可以分别访问行和列标签 :

注意:当一组特定的列与数据字典一起传递时,传递的列会覆盖字典中的键。

 来自 ndarrays / 列表的 dict

        ndarrays 必须都是相同的长度。如果传递了索引,它显然也必须与数组的长度相同。如果没有传递索引,则结果将为range(n),其中n是数组长度。

d = {"one": [1.0, 2.0, 3.0, 4.0], "two": [4.0, 3.0, 2.0, 1.0]}
d

pd.DataFrame(d)

pd.DataFrame(d, index=["a", "b", "c", "d"])

从结构化或记录数组

这种情况的处理方式与数组的 dict 相同。

data = np.zeros((2, ), dtype=[("A", "i4"), ("B", "f4"), ("C", "a10")])
data

data[:] = [(1, 2.0, "Hello"), (2, 3.0, "World")]
data

pd.DataFrame(data, index=["first", "second"])

pd.DataFrame(data, columns=["C", "A", "B"])

 从字典的列表:
data2 = [{"a": 1, "b": 2}, {"a": 5, "b": 10, "c": 20}]
pd.DataFrame(data2)

pd.DataFrame(data2, index=["first", "second"])

pd.DataFrame(data2, columns=["a", "b"])

从元组的字典

可以通过传递元组字典来自动创建 MultiIndexed 框架。

pd.DataFrame(
    {
        ("a", "b"): {("A", "B"): 1, ("A", "C"): 2},
        ("a", "a"): {("A", "C"): 3, ("A", "B"): 4},
        ("a", "c"): {("A", "B"): 5, ("A", "C"): 6},
        ("b", "a"): {("A", "C"): 7, ("A", "B"): 8},
        ("b", "b"): {("A", "D"): 9, ("A", "B"): 10},
    }
)

从命名元组列表中

        列表中第一个的字段名称namedtuple确定DataFrame. 剩下的命名元组(或元组)只是简单地解包,它们的值被输入到DataFrame. 如果这些元组中的任何一个比第一个短namedtuple,则相应行中后面的列被标记为缺失值。如果任何一个比第一个长namedtuple,则 aValueError被提高。

from collections import namedtuple

point = namedtuple("Point", "x y")
pd.DataFrame([point(0,0), point(0, 3), (2, 3)])

Point3D = namedtuple("Point3D", "x y z")
pd.DataFrame([Point3D(0, 0, 0), Point3D(0, 3, 5), point(2, 3)])

 从数据类列表中

PEP557中介绍的数据类可以传递到 DataFrame 构造函数中。传递数据类列表等同于传递字典列表。

请注意,列表中的所有值都应该是数据类,在列表中混合类型会导致 TypeError。

from dataclasses import make_dataclass
Point = make_dataclass("Point", [("x", int), ("y", int)])
pd.DataFrame([Point(0, 0), Point(0, 3), Point(2, 3)])

替代构造函数 DataFrame.from_dict

    DataFrame.from_dict接受 dicts 或类似数组序列的 dict 并返回一个 DataFrame。它的操作类似于DataFrame构造函数,除了默认情况下的orient参数'columns',但可以设置为'index'以便将 dict 键用作行标签。

pd.DataFrame.from_dict(dict([("A", [1, 2, 3]), ("B", [4, 5, 6])]))

 如果您通过orient='index',键将是行标签。在这种情况下,您还可以传递所需的列名:

pd.DataFrame.from_dict(
    dict([("A", [1, 2, 3]), ("B", [4, 5, 6])]),
    orient="index",
    columns=["one", "two", "three"],
)

DataFrame.from_records

    DataFrame.from_records接受元组列表或具有结构化 dtype 的 ndarray。它的工作方式与普通构造函数类似DataFrame,只是生成的 DataFrame 索引可能是结构化 dtype 的特定字段。例如:

pd.DataFrame.from_records(data, index="C")

 列选择、添加、删除

        可以在语义上将 DataFrame 视为类似索引的 Series 对象的字典。获取、设置和删除列的语法与类似的 dict 操作相同:

df["three"] = df["one"] * df["two"]
df

df["flag"] = df["one"] > 2
df

 列可以像字典一样被删除或弹出:

del df["two"]
df

three = df.pop("three")
three

 插入标量值时,自然会传播以填充列:

df["foo"] = "bar"

df

 在插入与 DataFrame 索引不同的 Series 时,将符合 DataFrame 的索引:

df["one_trunc"] = df["one"][:2]
df

可以插入原始 ndarray,但它们的长度必须与 DataFrame 索引的长度匹配。

默认情况下,列在最后插入。该insert函数可用于在列中的特定位置插入:

df.insert(1, "bar", df["one"])
df

 在方法链中分配新列

        受dplyr mutate动词的启发,DataFrame 有一种assign() 方法可以让您轻松创建可能从现有列派生的新列。

iris = pd.DataFrame(np.random.randn(600, 5), columns=["A", "B", "C", "D", "E"])
iris.head()

iris.assign(sepal_ratio=iris["B"] / iris["A"]).head()

         在上面的示例中,我们插入了一个预先计算的值。还可以传入一个参数的函数,以在分配给的 DataFrame 上进行评估。

iris.assign(sepal_ratio=lambda x: (x["B"] / x["A"])).head()

 assign 始终返回数据的副本,而原始 DataFrame 保持不变。

        当您手头没有对 DataFrame 的引用时,传递可调用对象而不是要插入的实际值很有用。assign这在一系列操作中使用时很常见。例如,我们可以将 DataFrame 限制为仅那些萼片长度大于 5 的观察值,计算比率并绘制:

(
        iris.query("A > 0").assign(
            F = lambda x: x.B / x.A,
            G = lambda x: x.D / x.C,
        ).plot(kind = "scatter", x = "F", y = "G")
)

        由于传入了一个函数,因此该函数是在分配给的 DataFrame 上计算的。重要的是,这是被过滤到A长度大于 0 的那些行的 DataFrame。过滤首先发生,然后是比率计算。这是一个示例,我们没有对可用的已过滤DataFrame 的引用。

        的函数签名assign很简单**kwargs。键是新字段的列名,值是要插入的值(例如,一个Series或 NumPy 数组),或者是要在DataFrame. 返回原始 DataFrame的副本,并插入新值。

        从 Python 3.6 开始,**kwargs保留了 的顺序。这允许依赖赋值,其中后面的表达式**kwargs可以引用前面创建的列assign()。

dfa = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})

dfa.assign(C=lambda x: x["A"] + x["B"], D=lambda x: x["A"] + x["C"])

 在第二个表达式中,x['C']将引用新创建的列,即等于。dfa['A'] + dfa['B']

索引/选择

索引的基础知识如下:

操作

句法

结果

选择列

df[col]

系列

按标签选择行

df.loc[label]

系列

按整数位置选择行

df.iloc[loc]

系列

切片行

df[5:10]

数据框

按布尔向量选择行

df[bool_vec]

数据框

例如,行选择返回一个 Series,其索引是 DataFrame 的列:

数据对齐和算术

        DataFrame 对象之间的数据对齐会自动对齐列和索引(行标签)。同样,生成的对象将具有列和行标签的联合。

df = pd.DataFrame(np.random.randn(10, 4), columns=["A", "B", "C", "D"])
df2 = pd.DataFrame(np.random.randn(7, 3), columns=["A", "B", "C"])
df + df2

        在 DataFrame 和 Series 之间进行操作时,默认行为是在 DataFrame列上对齐 Series索引,从而逐行广播 。例如:

df - df.iloc[0]

 标量运算与您预期的一样:

df * 5 + 2

1 / df

 布尔运算符也可以:

df1 = pd.DataFrame({"a": [1, 0, 1], "b": [0, 1, 1]}, dtype=bool)

df2 = pd.DataFrame({"a": [0, 1, 1], "b": [1, 1, 0]}, dtype=bool)

df1

 

Transposing

要转置,访问T属性(也是transpose函数),类似于 ndarray:

df[:5].T

DataFrame 与 NumPy 函数的互操作性

        Elementwise NumPy ufuncs (log, exp, sqrt, ...) 和其他各种 NumPy 函数可以在 Series 和 DataFrame 上毫无问题地使用,假设其中的数据是数字:

np.exp(df)

np.asarray(df)

DataFrame 并不打算成为 ndarray 的替代品,因为它的索引语义和数据模型在某些地方与 n 维数组完全不同。

Seriesimplements __array_ufunc__,这允许它与 NumPy 的 通用函数一起工作。

ufunc 应用于系列中的底层数组。

ser = pd.Series([1, 2, 3, 4])

np.exp(ser)

        与库的其他部分一样,pandas 将自动将标记的输入作为 ufunc 的一部分与多个输入对齐。例如,使用numpy.remainder() 两个Series具有不同顺序标签的标签将在操作之前对齐。 

ser1 = pd.Series([1, 2, 3], index=["a", "b", "c"])

ser2 = pd.Series([1, 3, 5], index=["b", "a", "c"])

ser1

np.remainder(ser1, ser2)

 像往常一样,取两个索引的并集,不重叠的值用缺失值填充。

ser3 = pd.Series([2, 4, 6], index=["b", "c", "d"])

ser3

np.remainder(ser1, ser3)
 

 当二进制 ufunc 应用于 a SeriesandIndex时,Series 实现优先并返回 Series。

        例如,NumPy ufunc 可以安全地应用于Series非 ndarray 数组的支持arrays.SparseArray(请参阅稀疏计算)。如果可能,应用 ufunc 而不将基础数据转换为 ndarray。

控制台显示

非常大的 DataFrame 将被截断以在控制台中显示它们。您还可以使用info(). 

df = pd.DataFrame(np.random.randn(100, 6))
df

df.info()

关注
打赏
1665675218
查看更多评论
立即登录/注册

微信扫码登录

0.2780s