Python 数学应用(二)(3)

简介: Python 数学应用(二)

Python 数学应用(二)(2)https://developer.aliyun.com/article/1506387

生成网络的邻接矩阵

在图的分析中,一个强大的工具是邻接矩阵,它的条目a[ij] = 1,如果有一条边从节点i到节点j,否则为 0。对于大多数网络,邻接矩阵将是稀疏的(大多数条目为 0)。对于非定向的网络,矩阵也将是对称的(a[ij] =a[ji])。还有许多其他可以与网络相关联的矩阵。我们将在本教程的更多内容…部分简要讨论这些。*

**在这个教程中,我们将生成网络的邻接矩阵,并学习如何从这个矩阵中获得网络的一些基本属性。

准备工作

在这个教程中,我们将需要将 NetworkX 包导入为nx,将 NumPy 模块导入为np

如何做…

以下步骤概述了如何为网络生成邻接矩阵,并从这个矩阵中推导出网络的一些简单属性:

  1. 首先,我们将生成一个网络,然后在整个教程中使用它。我们将生成一个具有五个节点和五条边的随机网络,同时使用一个种子以便重现:
G = nx.dense_gnm_random_graph(5, 5, seed=12345)
  1. 要生成邻接矩阵,我们使用 NetworkX 的adjacency_matrix例程。这默认返回一个稀疏矩阵,因此我们还将使用todense方法将其转换为完整的 NumPy 数组以进行演示:
matrix = nx.adjacency_matrix(G).todense()
print(matrix)
# [[0 0 1 0 0]
#  [0 0 1 1 0]
#  [1 1 0 0 1]
#  [0 1 0 0 1]
#  [0 0 1 1 0]]
  1. 对邻接矩阵进行n次幂运算可以得到从一个节点到另一个节点的长度为n的路径数:
paths_len_4 = np.linalg.matrix_power(matrix, 4)
print(paths_len_4)
# [[ 3 5  0  0 5]
#  [ 5 9  0  0 9]
#  [ 0 0 13 10 0]
#  [ 0 0 10  8 0]
#  [ 5 9  0  0 9]]

它是如何工作的…

dense_gnm_random_graph例程生成一个(密集的)随机网络,从所有具有n个节点和m条边的网络家族中均匀选择。在这个教程中,n=5m=5。密集前缀表示这个例程使用的算法应该比对于节点数相对较大的密集网络的替代gnm_random_graph更快。

网络的邻接矩阵很容易生成,特别是在图相对较小的情况下,尤其是在稀疏形式下。对于更大的网络,这可能是一个昂贵的操作,因此可能不太实际,特别是如果你将其转换为完整矩阵,就像我们在这个教程中看到的那样。一般来说,你不需要这样做,因为我们可以简单地使用adjacency_matrix例程生成的稀疏矩阵和 SciPy sparse模块中的稀疏线性代数工具。

矩阵的幂提供了关于给定长度的路径数的信息。通过追踪矩阵乘法的定义,这很容易看出。请记住,当两个给定节点之间存在边(长度为 1 的路径)时,邻接矩阵的条目为 1。

更多内容…

网络的邻接矩阵的特征值提供了关于网络结构的一些额外信息,例如网络色数的上下界。(有关网络着色的更多信息,请参见着色网络教程。)有一个单独的例程用于计算邻接矩阵的特征值。例如,我们可以使用adjacency_spectrum例程生成网络的邻接矩阵的特征值。与网络相关的矩阵的特征值的方法通常被称为谱方法

与网络相关的还有其他矩阵,如关联矩阵拉普拉斯矩阵。网络的关联矩阵是一个M × N矩阵,其中M是节点数,N是边数。如果节点i出现在边j中,则该矩阵的第i-j个条目为 1,否则为 0。网络的拉普拉斯矩阵被定义为L = D - A矩阵,其中D是包含网络中节点度数的对角线矩阵,A是网络的邻接矩阵。这些矩阵对于分析网络很有用。

创建定向和加权网络

简单的网络,比如前面的教程中描述的那些,用于描述边的方向不重要且边的权重相等的网络是有用的。实际上,大多数网络都携带额外的信息,比如权重或方向。

在这个教程中,我们将创建一个有向且带权重的网络,并探索这种网络的一些基本属性。

准备工作

对于这个教程,我们将需要 NetworkX 包,以通常的方式导入为nx,导入为plt的 Matplotlibpyplot模块,以及导入为np的 NumPy 包。

如何操作…

以下步骤概述了如何创建一个带权重的有向网络,以及如何探索我们在前面教程中讨论的一些属性和技术:

  1. 为了创建一个有向网络,我们使用 NetworkX 中的DiGraph类,而不是简单的Graph类:
G = nx.DiGraph()
  1. 像往常一样,我们使用add_nodeadd_nodes_from方法向网络添加节点:
G.add_nodes_from(range(5))
  1. 要添加加权边,我们可以使用add_edge方法并提供weight关键字参数,或者使用add_weighted_edges_from方法:
G.add_edge(0, 1, weight=1.0)
G.add_weighted_edges_from([
    (1, 2, 0.5), (1, 3, 2.0), (2, 3, 0.3), (3, 2, 0.3),
    (2, 4, 1.2), (3, 4, 0.8)
])
  1. 接下来,我们用箭头绘制网络,以指示每条边的方向。我们还为这个图提供了自己的位置:
fig, ax = plt.subplots()
pos = {0: (-1, 0), 1: (0, 0), 2: (1, 1), 3: (1, -1), 4: (2, 0)}
nx.draw(G, ax=ax, pos=pos, with_labels=True)
ax.set_title("Weighted, directed network")

可以在下图中看到得到的图:

图 5.3:一个带权重的有向网络

  1. 有向矩阵的邻接矩阵的创建方式与简单网络相同,但是得到的矩阵不会是对称的:
adj_mat = nx.adjacency_matrix(G).todense()
print(adj_mat)
# [[0\. 1\. 0\. 0\. 0\. ]
# [0\. 0\. 0.5 2\. 0\. ]
# [0\. 0\. 0\. 0.3 1.2]
# [0\. 0\. 0.3 0\. 0.8]
# [0\. 0\. 0\. 0\. 0\. ]]

工作原理…

DiGraph类表示一个有向网络,其中在添加边时节点的顺序很重要。在这个教程中,我们添加了两条连接节点 2 和 3 的边,每个方向一条。在简单网络(Graph类)中,添加第二条边不会增加额外的边。然而,在有向网络(DiGraph类)中,添加边时给出的节点的顺序决定了方向。

关于加权边,除了添加附加到边的weight属性之外,没有什么特别之处。(可以通过关键字参数向网络中的边或节点附加任意数据。)add_weighted_edges_from方法只是将相应的权重值(元组中的第三个值)添加到相关的边上。权重可以添加到任何网络中的任何边,而不仅仅是本教程中显示的有向网络。

在绘制有向网络时,draw例程会自动向边添加箭头。可以通过传递arrows=False关键字参数来关闭这种行为。有向或带权重网络的邻接矩阵也与简单网络不同。在有向网络中,矩阵通常不对称,因为边可能只存在一个方向而不是另一个方向。对于带权重的网络,条目可以不同于 1 或 0,而是对应边的权重。

还有更多…

带权重的网络出现在许多应用中,比如用距离或速度描述交通网络。您还可以使用网络来通过为网络中的边提供“容量”(作为权重或其他属性)来研究网络中的流动。NetworkX 有几个工具用于分析网络中的流动,比如通过nx.maximum_flow例程找到网络中的最大流量。

有向网络为网络添加了方向信息。许多现实世界的应用产生了具有单向边的网络,比如工业流程或供应链网络中的网络。这种额外的方向信息对许多处理网络的算法都有影响,我们将在本章中看到。

在网络中查找最短路径

网络出现的一个常见问题是在网络中找到两个节点之间的最短路径或者更准确地说是最高奖励的路径。例如,这可能是两个城市之间的最短距离,其中节点代表城市,边代表连接城市对的道路。在这种情况下,边的权重将是它们的长度。

在这个示例中,我们将在一个带权重的网络中找到两个节点之间的最短路径。

准备工作

对于这个示例,我们将需要导入 NetworkX 包,通常使用nx作为名称,导入 Matplotlib 的pyplot模块作为plt,以及从 NumPy 导入一个随机数生成器对象:

from numpy.random import default_rng
rng = default_rng(12345) # seed for reproducibility

如何做…

按照以下步骤在网络中找到两个节点之间的最短路径:

  1. 首先,我们将使用gnm_random_graph和一个seed创建一个随机网络,用于这个演示:
G = nx.gnm_random_graph(10, 17, seed=12345)
  1. 接下来,我们将以圆形排列的方式绘制网络,以查看节点之间的连接方式:
fig, ax = plt.subplots()
nx.draw_circular(G, ax=ax, with_labels=True)
ax.set_title("Random network for shortest path finding")

生成的图可以在下面的图片中看到。在这里,我们可以看到从节点 7 到节点 9 没有直接的边:

图 5.4:一个随机生成的具有 10 个节点和 17 条边的网络

  1. 现在,我们需要给每条边添加权重,以便在最短路径方面有些路线更可取:
for u, v in G.edges:
    G.edges[u, v]["weight"] = rng.integers(5, 15)
  1. 接下来,我们将使用nx.shortest_path例程计算从节点 7 到节点 9 的最短路径:
path = nx.shortest_path(G, 7, 9, weight="weight")
print(path)
# [7, 5, 2, 9]
  1. 我们可以使用nx.shortest_path_来找到这条最短路径的长度

长度routine

length = nx.shortest_path_length(G, 7, 9, weight="weight")
print("Length", length)
# Length 32

它是如何工作的…

shortest_path例程计算每对节点之间的最短路径。或者,当提供源节点和目标节点时,就像我们在这个示例中所做的那样,它计算两个指定节点之间的最短路径。我们提供了可选的weight关键字参数,这使算法根据边的“权重”属性找到最短路径。这个参数改变了“最短”的含义,默认是“最少的边”。

找到两个节点之间最短路径的默认算法是 Dijkstra 算法,这是计算机科学和数学课程的基础。它是一个很好的通用算法,但效率并不是特别高。其他寻路算法包括 A算法。使用 A算法并提供额外的启发式信息来指导节点选择可以获得更高的效率。

还有更多…

有许多算法可以在网络中找到两个节点之间的最短路径。还有一些变体用于找到最大加权路径。

关于在网络中找到路径的问题还有一些相关问题,比如旅行推销员问题路线检查问题。在旅行推销员问题中,我们找到一个循环(从同一个节点开始和结束的路径),访问网络中的每个节点,总权重最小(或最大)。在路线检查问题中,我们寻找通过网络中每条边并返回到起点的最短循环(按权重计算)。已知旅行推销员问题是 NP 难题,但路线检查问题可以在多项式时间内解决。

图论中一个著名的问题是 Königsberg 的桥,它要求在网络中找到一条路径,该路径恰好穿过网络中的每条边一次。事实证明,正如欧拉证明的那样,在 Königsberg 桥问题中找到这样的路径是不可能的。穿过每条边恰好一次的路径称为欧拉回路。如果一个网络允许欧拉回路,则称为欧拉。事实上,当且仅当每个节点的度都是偶数时,网络才是欧拉的。Königsberg 桥问题的网络表示如下图所示。这里的边代表河流上的不同桥梁,而节点代表不同的陆地。我们可以看到所有四个节点的度都是奇数,这意味着不能有一条穿过每条边恰好一次的路径:

图 5.5:表示 Königsberg 桥问题的网络

边代表节点之间的桥梁。

在网络中量化聚类

与网络相关的各种量度可以衡量网络的特性。例如,节点的聚类系数衡量了附近节点之间的互连性(这里,附近意味着通过边连接)。实际上,它衡量了邻近节点接近形成一个完整网络或的程度。

节点的聚类系数衡量了与该节点相邻的节点之间通过边连接的比例;也就是说,两个相邻的节点与给定节点形成一个三角形。我们计算三角形的数量,并将其除以可能形成的总三角形数量,考虑到节点的度。从数值上看,简单无权重网络中节点u的聚类系数由以下方程给出:

这里,T[u]u处的三角形数,分母是u处可能的三角形总数。如果u的度(u的边数)为 0 或 1,则将*c[u]*设为 0。

在这个示例中,我们将学习如何计算网络中节点的聚类系数。

准备工作

对于这个示例,我们需要导入 NetworkX 包作为nx,并导入 Matplotlib pyplot模块作为plt

如何做…

以下步骤向您展示了如何计算网络中节点的聚类系数:

  1. 首先,我们需要创建一个样本网络来使用:
G = nx.Graph()
complete_part = nx.complete_graph(4)
cycle_part = nx.cycle_graph(range(4, 9))
G.update(complete_part)
G.update(cycle_part)
G.add_edges_from([(0, 8), (3, 4)])
  1. 接下来,我们将绘制网络,以便比较我们将要计算的聚类系数。这将使我们能够看到这些节点在网络中的出现方式:
fig, ax = plt.subplots()
nx.draw_circular(G, ax=ax, with_labels=True)
ax.set_title("Network with different clustering behavior")

结果图可以在下图中看到:

图 5.6:用于测试聚类的示例网络

  1. 现在,我们可以使用nx.clustering例程计算网络中节点的聚类系数:
cluster_coeffs = nx.clustering(G)
  1. nx.clustering例程的输出是网络中节点的字典。因此,我们可以按如下方式打印一些选定的节点:
for i in [0, 2, 6]:
    print(f"Node {i}, clustering {cluster_coeffs[i]}")
# Node 0, clustering 0.5
# Node 2, clustering 1.0
# Node 6, clustering 0
  1. 可以使用nx.average_clustering例程计算网络中所有节点的平均聚类系数:
av_clustering = nx.average_clustering(G)
print(av_clustering)
# 0.3333333333333333

它是如何工作的…

节点的聚类系数衡量了该节点的邻域接近形成一个完整网络(所有节点彼此连接)。在这个示例中,我们可以看到我们有三个不同的计算值:0 的聚类系数为 0.5,2 的聚类系数为 1.0,6 的聚类系数为 0。这意味着连接到节点 2 的节点形成了一个完整的网络,这是因为我们设计了我们的网络。 (节点 0-4 按设计形成一个完整的网络。)节点 6 的邻域离完整很远,因为它的邻居之间没有相互连接的边。

平均聚类值是网络中所有节点的聚类系数的简单平均值。它与全局聚类系数(使用 NetworkX 中的nx.transitivity例程计算)不完全相同,但它确实让我们了解整个网络接近完全网络的程度。全局聚类系数衡量了三角形的数量与三元组的数量之比 - 由至少两条边连接的三个节点组成 - 在整个网络上。

平均聚类之间的差异非常微妙。全局聚类系数衡量了整个网络的聚类程度,但平均聚类系数衡量了网络在局部平均聚类的程度。这种差异最好在风车网络中看到,它由一个单一节点围绕着偶数个节点的圆圈组成。所有节点都连接到中心,但圆圈上的节点只以交替模式连接。外部节点的局部聚类系数为 1,而中心节点的局部聚类系数为 1/(2N-1),其中N表示连接到中心节点的三角形的数量。然而,全局聚类系数为 3/(2N-1)。

还有更多…

聚类系数与网络中的相关。团是一个完全的子网络(所有节点都通过一条边连接)。网络理论中的一个重要问题是找到网络中的最大团,这在一般情况下是一个非常困难的问题(这里,最大意味着“不能再扩大”)。

着色网络

网络在调度问题中也很有用,您需要将活动安排到不同的时间段中,以确保没有冲突。例如,我们可以使用网络来安排课程,以确保选择不同选项的学生不必同时上两节课。在这种情况下,节点将代表不同的课程,边将指示有学生同时上两门课。我们用来解决这类问题的过程称为网络着色。这个过程涉及为网络中的节点分配尽可能少的颜色,以便相邻的两个节点没有相同的颜色。

在本教程中,我们将学习如何着色网络以解决简单的调度问题。

准备工作

对于本教程,我们需要导入 NetworkX 包为nx,导入 Matplotlib 的pyplot模块为plt

如何做…

按照以下步骤解决网络着色问题:

  1. 首先,我们将创建一个示例网络,用于本教程:
G = nx.complete_graph(3)
G.add_nodes_from(range(3, 7))
G.add_edges_from([
    (2, 3), (2, 4), (2, 6), (0, 3), (0, 6), (1, 6),
    (1, 5), (2, 5), (4, 5)
])
  1. 接下来,我们将绘制网络,以便在生成着色时能够理解。为此,我们将使用draw_circular例程:
fig, ax = plt.subplots()
nx.draw_circular(G, ax=ax, with_labels=True)
ax.set_title("Scheduling network")

生成的绘图如下图所示:

图 5.7:简单调度问题的示例网络

  1. 我们将使用nx.greedy_color例程生成着色:
coloring = nx.greedy_color(G)
print("Coloring", coloring)
# Coloring {2: 0, 0: 1, 1: 2, 5: 1, 6: 3, 3: 2, 4: 2}
  1. 要查看此着色中使用的实际颜色,我们将从coloring字典生成一组值:
different_colors = set(coloring.values())
print("Different colors", different_colors)
# Different colors {0, 1, 2, 3}

它是如何工作的…

nx.greedy_color例程使用多种可能的策略对网络进行着色。默认情况下,它按照从最大到最小的顺序按度数工作。在我们的情况下,它首先为度为 6 的节点 2 分配颜色 0,然后为度为 4 的节点 0 分配颜色 1,依此类推。对于这个序列中的每个节点,选择第一个可用的颜色。这不一定是着色网络的最有效算法。

显然,通过为每个节点分配不同的颜色,可以给任何网络上色,但在大多数情况下,需要更少的颜色。在本教程中,网络有七个节点,但只需要四种颜色。所需的最小颜色数称为网络的色数

还有更多…

网络的着色问题有几种变体。其中一种变体是列表着色问题,在这个问题中,我们寻找一个网络的着色,其中每个节点从可能颜色的预定义列表中选择一个颜色。这个问题显然比一般的着色问题更困难。

一般着色问题有一些令人惊讶的结果。例如,每个平面网络最多可以用四种不同的颜色着色。这是图论中著名的四色定理,由 Appel 和 Haken 在 1977 年证明。

找到最小生成树和支配集

网络在各种问题中都有应用。两个明显的领域是通信和分配。例如,我们可能希望找到一种在覆盖从特定点到许多城市(节点)的道路网络中最小距离的分配方式。对于这样的问题,我们需要查看最小生成树和支配集。

在这个教程中,我们将在网络中找到一个最小生成树和一个支配集。

准备工作

对于这个教程,我们需要将 NetworkX 包导入为nx,将 Matplotlib 的pyplot模块导入为plt

如何做…

按照以下步骤找到网络的最小生成树和支配集:

  1. 首先,我们将创建一个样本网络进行分析:
G = nx.gnm_random_graph(15, 22, seed=12345)
  1. 接下来,和往常一样,在进行任何分析之前,我们将绘制网络:
fig, ax = plt.subplots()
pos = nx.circular_layout(G)
nx.draw(G, pos=pos, ax=ax, with_labels=True)
ax.set_title("Network with minimum spanning tree overlaid")
  1. 最小生成树可以使用nx.minimum_来计算

生成树`例程:

min_span_tree = nx.minimum_spanning_tree(G)
print(list(min_span_tree.edges))
# [(0, 13), (0, 7), (0, 5), (1, 13), (1, 11),
#   (2, 5), (2, 9), (2, 8), (2, 3), (2, 12),
#   (3, 4), (4, 6), (5, 14), (8, 10)]
  1. 接下来,我们将在绘图上叠加最小生成树的边:
nx.draw_networkx_edges(min_span_tree, pos=pos, ax=ax, width=1.5,
   edge_color="r")
  1. 最后,我们将使用nx.dominating_set例程为网络找到一个支配集-一个集合,其中网络中的每个节点都与支配集中的至少一个节点相邻:
dominating_set = nx.dominating_set(G)
print("Dominating set", dominating_set)
# Dominating set {0, 1, 2, 4, 10, 14}

可以在下图中看到叠加了最小生成树的网络的绘图:

图 5.8:叠加了最小生成树的网络绘制

它是如何工作的…

网络的生成树是网络中包含所有节点的树。最小生成树是包含尽可能少的边的生成树,或者说具有最低的总权重。最小生成树对于网络上的分配问题非常有用。一种简单的找到最小生成树的算法是简单地选择边(如果网络是加权的,则首先选择最小权重的边),以便不会创建循环,直到不再可能为止。

网络的支配集是一个顶点集,其中网络中的每个节点都与支配集中的至少一个节点相邻。支配集在通信网络中有应用。我们经常有兴趣找到最小的支配集,但这在计算上是困难的。事实上,测试是否存在一个比给定大小更小的支配集是 NP 完全的。然而,对于某些类别的图形,有一些有效的算法可以找到最小的支配集。非正式地说,问题在于一旦你确定了一个最小大小支配集的候选者,你必须验证是否存在比它更小的支配集。如果你事先不知道所有可能的支配集,这显然是非常困难的。

进一步阅读

有几本经典的图论著作,包括 Bollobás 和 Diestel 的书:

  • Diestel, R., 2010. Graph Theory. 3rd ed. Berlin: Springer.*
  • Bollobás, B., 2010. Modern Graph Theory. New York, NY: Springer.***

第七章:处理数据和统计

对于需要分析数据的人来说,Python 最吸引人的特点之一是数据操作和分析软件包的庞大生态系统,以及与 Python 合作的数据科学家活跃的社区。Python 使用起来很容易,同时还提供非常强大、快速的库,使得即使是相对新手的程序员也能够快速、轻松地处理大量数据。许多数据科学软件包和工具的核心是 pandas 库。Pandas 提供了两种数据容器类型,它们建立在 NumPy 数组的基础上,并且对于标签(除了简单的整数)有很好的支持。它们还使得处理大量数据变得非常容易。

统计学是使用数学—特别是概率—理论对数据进行系统研究。统计学有两个方面。第一个是找到描述一组数据的数值,包括数据的中心(均值或中位数)和离散程度(标准差或方差)等特征。统计学的第二个方面是推断,使用相对较小的样本数据集来描述一个更大的数据集(总体)。

在本章中,我们将看到如何利用 Python 和 pandas 处理大量数据并进行统计测试。

本章包含以下示例:

  • 创建 Series 和 DataFrame 对象
  • 从 DataFrame 中加载和存储数据
  • 在数据框中操作数据
  • 从 DataFrame 绘制数据
  • 从 DataFrame 获取描述性统计信息
  • 使用抽样了解总体
  • 使用 t 检验来测试假设
  • 使用方差分析进行假设检验
  • 对非参数数据进行假设检验
  • 使用 Bokeh 创建交互式图表

技术要求

在本章中,我们将主要使用 pandas 库进行数据操作,该库提供了类似于 R 的数据结构,如 SeriesDataFrame 对象,用于存储、组织和操作数据。我们还将在本章的最后一个示例中使用 Bokeh 数据可视化库。这些库可以使用您喜欢的软件包管理器(如 pip)进行安装:

python3.8 -m pip install pandas bokeh

我们还将使用 NumPy 和 SciPy 软件包。

本章的代码可以在 GitHub 代码库的 Chapter 06 文件夹中找到:github.com/PacktPublishing/Applying-Math-with-Python/tree/master/Chapter%2006

查看以下视频以查看代码示例:bit.ly/2OQs6NX

创建 Series 和 DataFrame 对象

Python 中的大多数数据处理都是使用 pandas 库完成的,它构建在 NumPy 的基础上,提供了类似于 R 的数据结构来保存数据。这些结构允许使用字符串或其他 Python 对象而不仅仅是整数来轻松索引行和列。一旦数据加载到 pandas 的 DataFrameSeries 中,就可以轻松地进行操作,就像在电子表格中一样。这使得 Python 结合 pandas 成为处理和分析数据的强大工具。

在本示例中,我们将看到如何创建新的 pandas SeriesDataFrame 对象,并访问 SeriesDataFrame 中的项目。

准备工作

对于这个示例,我们将使用以下命令导入 pandas 库:

import pandas as pd

NumPy 软件包是 np。我们还可以从 NumPy 创建一个(种子)随机数生成器,如下所示:

from numpy.random import default_rng
rng = default_rng(12345)

如何做…

以下步骤概述了如何创建包含数据的 SeriesDataFrame 对象:

  1. 首先,创建我们将存储在 SeriesDataFrame 对象中的随机数据:
diff_data = rng.normal(0, 1, size=100)
cumulative = np.add.accumulate(diff_data)
  1. 接下来,创建一个包含 diff_dataSeries 对象。我们将打印 Series 以查看数据的视图:
data_series = pd.Series(diff_data)
print(data_series)
  1. 现在,创建一个具有两列的 DataFrame 对象:
data_frame = pd.DataFrame({
   "diffs": data_series,
    "cumulative": cumulative
}) 
  1. 打印 DataFrame 对象以查看其包含的数据:
print(data_frame)

它是如何工作的…

pandas 包提供了SeriesDataFrame类,它们反映了它们的 R 对应物的功能和能力。Series用于存储一维数据,如时间序列数据,DataFrame用于存储多维数据;您可以将DataFrame对象视为"电子表格"。

Series与简单的 NumPy ndarray的区别在于Series索引其项的方式。NumPy 数组由整数索引,这也是Series对象的默认索引。但是,Series可以由任何可散列的 Python 对象索引,包括字符串和datetime对象。这使得Series对于存储时间序列数据非常有用。Series可以以多种方式创建。在这个示例中,我们使用了 NumPy 数组,但是任何 Python 可迭代对象,如列表,都可以替代。

DataFrame 对象中的每一列都是包含行的系列,就像传统数据库或电子表格中一样。在这个示例中,当通过字典的键构造 DataFrame 对象时,列被赋予标签。

DataFrameSeries对象在打印时会创建它们包含的数据的摘要。这包括列名、行数和列数,以及框架(系列)的前五行和最后五行。这对于快速获取对象和包含的数据的概述非常有用。

还有更多…

Series对象的单个行(记录)可以使用通常的索引符号通过提供相应的索引来访问。我们还可以使用特殊的iloc属性对象按其数值位置访问行。这允许我们按照它们的数值(整数)索引访问行,就像 Python 列表或 NumPy 数组一样。

可以使用通常的索引符号访问DataFrame对象中的列,提供列的名称。这样做的结果是一个包含所选列数据的Series对象。DataFrames 还提供了两个属性,可以用来访问数据。loc属性提供对个别行的访问,无论这个对象是什么。iloc属性提供按数值索引访问行,就像Series对象一样。

您可以向loc(或只使用对象的索引符号)提供选择条件来选择数据。这包括单个标签、标签列表、标签切片或布尔数组(适当大小的数组)。iloc选择方法接受类似的条件。

除了我们在这里描述的简单方法之外,还有其他从 Series 或 DataFrame 对象中选择数据的方法。例如,我们可以使用at属性来访问对象中指定行(和列)的单个值。

另请参阅

pandas 文档包含了创建和索引 DataFrame 或 Series 对象的不同方法的详细描述,网址为pandas.pydata.org/docs/user_guide/indexing.html

从 DataFrame 加载和存储数据

在 Python 会话中从原始数据创建 DataFrame 对象是相当不寻常的。实际上,数据通常来自外部来源,如现有的电子表格或 CSV 文件、数据库或 API 端点。因此,pandas 提供了许多用于加载和存储数据到文件的实用程序。pandas 支持从 CSV、Excel(xls 或 xlsx)、JSON、SQL、Parquet 和 Google BigQuery 加载和存储数据。这使得将数据导入 pandas 然后使用 Python 操纵和分析这些数据变得非常容易。

在这个示例中,我们将看到如何将数据加载和存储到 CSV 文件中。加载和存储数据到其他文件格式的指令将类似。

做好准备

对于这个示例,我们需要导入 pandas 包作为pd别名和 NumPy 库作为np,并使用以下命令创建一个默认的随机数生成器:

from numpy.random import default_rng
rng = default_rng(12345) # seed for example

如何做…

按照以下步骤将数据存储到文件,然后将数据加载回 Python:

  1. 首先,我们将使用随机数据创建一个样本DataFrame对象。然后打印这个DataFrame对象,以便我们可以将其与稍后将要读取的数据进行比较:
diffs = rng.normal(0, 1, size=100)
cumulative = np.add.accumulate(diffs)
data_frame = pd.DataFrame({
    "diffs": diffs, 
    "cumulative": cumulative
})
print(data_frame)
  1. 我们将使用DataFrame对象中的数据将数据存储到sample.csv文件中,使用DataFrame对象上的to_csv方法。我们将使用index=False关键字参数,以便索引不存储在 CSV 文件中:
data_frame.to_csv("sample.csv", index=False)
  1. 现在,我们可以使用 pandas 中的read_csv例程将sample.csv文件读入一个新的DataFrame对象。我们将打印这个对象以显示结果:
df = pd.read_csv("sample.csv", index_col=False)
print(df)

它是如何工作的…

这个示例的核心是 pandas 中的read_csv例程。这个例程以路径或类文件对象作为参数,并将文件的内容读取为 CSV 数据。我们可以使用sep关键字参数自定义分隔符,默认为逗号(,)。还有一些选项可以自定义列标题和自定义每列的类型。

DataFrameSeries中的to_csv方法将内容存储到 CSV 文件中。我们在这里使用了index关键字参数,以便索引不会打印到文件中。这意味着 pandas 将从 CSV 文件中的行号推断索引。如果数据是由整数索引的,这种行为是可取的,但如果数据是由时间或日期索引的,情况可能不同。我们还可以使用这个关键字参数来指定 CSV 文件中的哪一列是索引列。

另请参阅

请参阅 pandas 文档,了解支持的文件格式列表pandas.pydata.org/docs/reference/io.html

Python 数学应用(二)(4)https://developer.aliyun.com/article/1506398

相关文章
|
4天前
|
大数据 Python
Python中for循环的嵌套应用
Python中for循环的嵌套应用
17 1
|
3天前
|
存储 索引 Python
元组(Tuple)在Python编程中的应用与实例
元组(Tuple)在Python编程中的应用与实例
14 2
|
4天前
|
大数据 Python
Python中while循环的嵌套应用详解
Python中while循环的嵌套应用详解
13 0
|
4天前
|
Python
Python中的判断语句:深入解析与应用
Python中的判断语句:深入解析与应用
12 0
|
4天前
|
索引 Python
Python中的字符串格式化:详解与应用
Python中的字符串格式化:详解与应用
12 0
|
4天前
|
缓存 自然语言处理 数据库
构建高效Python Web应用:异步编程与Tornado框架
【5月更文挑战第30天】在追求高性能Web应用开发的时代,异步编程已成为提升响应速度和处理并发请求的关键手段。本文将深入探讨Python世界中的异步编程技术,特别是Tornado框架如何利用非阻塞I/O和事件循环机制来优化Web服务的性能。我们将剖析Tornado的核心组件,并通过实例演示如何构建一个高效的Web服务。
|
3天前
|
存储 算法 数据处理
字典在Python中的应用与实例
字典在Python中的应用与实例
13 1
|
3天前
|
数据处理 Python
Python函数:深入理解与应用
Python函数:深入理解与应用
6 1
|
4天前
|
算法 Python
Python函数的嵌套调用:深入理解与应用
Python函数的嵌套调用:深入理解与应用
9 1
|
5天前
|
机器学习/深度学习 数据采集 监控
基于Python的图像识别技术在智能安防系统中的应用
【5月更文挑战第30天】 在当今社会,随着人工智能技术的飞速发展,图像识别已经成为了一个重要的研究领域。本文将介绍基于Python的图像识别技术在智能安防系统中的应用,通过对深度学习模型的讲解和实例分析,展示了如何利用Python实现高效、准确的图像识别功能,为智能安防系统的设计和实现提供了有力的技术支持。