NumPy一维数组、二维数组与Pandas的Series、DataFrame行列结构和横纵方向的统一说明

news2025/1/19 3:37:37

最近在这个问题上耽误了一些时间,原因是之前个人理解上出了一些偏差,又受到错误文章的误导,把这个问题搞复杂了,现在统一梳理一下。在展开之前,先明确说明的是:NumPy的二维数组与Pandas的DataFrame,它们的横纵方向和行列结构完全遵循常规,它们的字面量形式与常规二维表格数据(如CSV)的书写和阅读习惯一致,不存在任何“反常识”或“反直觉”的设计。

1.(在NumPy二维数组中的)一维数组是“行”还是“列”?

是“行”。首先,我们应该清楚一点:一维数组本身是没有“横向”和“纵向”概念的,站在一维数组里,我们只能分清是“向前”还是“向后”,即:在任何一个单一维度里,“方向”只有“正向”和“反向”之分。之所以会这样问是因为:一维数组是组成二维数组的基础元素,受二维数组对应二维表格的影响,人们需要确定一维数组对应的是表格中的“行”还是“列”。

和所有编程语言一样,在NumPy二维数组中的一维数组对应的是“行”,这个问题简单清楚,无需讨论。但是此前个人在理解这个问题时犯了一个低级错误:由于DataFrame是由Series构成的,既然使用NumPy二维数组可以构建DataFrame,于是就想当然地认为:NumPy二维数组中的一维数组和DataFrame里面的Series是一一对应的,由于Series是面向列设计的,所以就错误地把一维数组也理解为纵向的列了,进而认为NumPy的二维数组是由其内部一维数组以列的形式填充起来的。

所以,虽然很基础,但还是要再次强调一下:尽管我们可以简单地认为NumPy的二维数组对应Pandas的DataFrame,但是NumPy二维数组中的一维数组绝不对应DataFrame的Series,前者是一“行”数据,后者则是一“列”数据

2.(在DataFrame中的)Series是“行”还是“列”?

是“列”。Series是DataFrame独有的数据结构,是构成DataFrame的下层数据结构,它是专门面向“列”设计的。我们先通过一张形象的Series结构示意图(图片引用自微信公众号:数据统计学)了解一下Series:

在这里插入图片描述
首先Series是有Index(行标签)的,其次,我们可以从DataFrame中取出一个Series打印一下内容就清楚了:

import numpy as np
import pandas as pd

a = np.array([[1, 1, 1],
              [2, 2, 2]])
df = pd.DataFrame(a, columns=['col1', 'col2', 'col3'], index=['row1', 'row2'])
# 直接使用列名即可得到对应的Series
s = df.col1
print(f"type of s: {type(s)}")
print(f"data of s: {s}")

程序输出:

type of s: <class 'pandas.core.series.Series'>
data of s: row1    1
row2    2
Name: col1, dtype: int32

可见,在DataFrame,可以直接使用列名取出一个Series。

3. NumPy二维数组与DataFrame行列结构是否一致?

完全一致!它们的字面量形式与常规二维表格数据(如CSV)的行列布局一致:横向为行,纵向为列。符合常识,也遵循人们的使用习惯。以CSV数据为例:

name,gender,age
jack,male,23
rose,female,21

这是最常见的二维表格形态的数据,横向为行,纵向为列,人们非常习惯书写和阅读这种表达形式的二维数据。NumPy和Pandas不会设计与人们使用习惯向左的数据结构,使用NumPy二维数组表示上述CSV数据的表达式是:

import numpy as np
import pandas as pd
# 使用二维数组定义二维表格数据遵循人们的使用习惯:横向为行,纵向为列
roster = np.array([['jack', 'male', '23'],
                   ['rose', 'female', '21']])
# 输出的行列数也是按人们的使用习惯定义的:(行,列)
print(f"shape of roster: {roster.shape}")
print(f"data of roster: \n{roster}")

程序输出:

shape of roster: (2, 3)
data of roster: 
[['jack' 'male' '23']
 ['rose' 'female' '21']]

按下来,我们再把这个NumPy的二维数组填充到一个DataFrame中,

roster = pd.DataFrame(roster, columns=['name', 'gender', 'age'])

print(f"shape of roster: {roster.shape}")
print(f"data of roster: \n{roster}")

程序输出:

shape of roster: (2, 3)
data of roster: 
   name  gender age
0  jack    male  23
1  rose  female  21

从几乎无差异的输出可以看出:DataFrame和NumPy对二维数据的“行”、“列”认定是一致的,也都遵从了人们的使用习惯

4. 关于轴向(Axis)的再思考

在梳理完DataFrame和NumPy对二维数据的“行”、“列”认定方式后,我们再来思考一下轴向(Axis),我们知道Axis=0是纵向,Axis=1是横向,此前,个人曾写过一篇文章讨论如何理解和记忆它们,实际上,结合今天讨论的“行”、“列”问题,我突然意识到,或许很强有力的理由是:习惯!在一个二维表格里,聚合和过滤一般是面向什么操作的?列!求总和,求均值,这些操作都是在列上进行的,SQL中大量的函数都是面向列的聚合计算,既然列是主要的轴向操作,那么就应该设为默认值,从而不必每次显式设定,既然又是从0编码,不如就用初值0代表默认轴向(纵向),然后axis参数默认赋初值0,默认按列聚合或过滤,一切遵循默认的使用习惯,这大概是轴向(Axis)如此定义的主要原因吧。

5. 两处容易出错的细节

最后,梳理一下近期在学习和使用DataFrame和NumPy过程中犯的两处与二维数据行列结构有关的错误:

(1) 当我们使用已有的一维数组去构建一个DataFrame时,要注意一下你手上的一维数组是行数据还是列数据,不要弄混,只有使用行数据构建才能得到符合预期的结果,如果是列数据,一定要使用DataFrame的列式构建形成创建DataFrame。此前在研究正态分布时,曾经分别生成过heights和weights两个数组,后来需要将它们合并一个二维数组显示在散点图中,横轴为height,纵轴为weight,于是就按下面的方式构建了DataFrame:

heights = np.random.normal(loc=170, scale=4, size=100)
weights = np.random.normal(loc=60, scale=4, size=100)
# 一个搞混了行列结构的错误示例
heights_weights = pd.DataFrame([heights,weights])
....

这里犯的错误就是把放有同一类数据本改当“列”的一维数组错当成了行,导致数组结构完全错位。修正方法就是使用DataFrame的列式构建形式创建它:pd.DataFrame({'height':heights, 'weight': weights})

(2) 依然是前面提到过的问题,虽然Series是组成DataFrame的下层数据结构,但是:这并不代表使用NumPy二维数组填充DataFrame时里面的一维数组会被封装成Series,从而变成了DataFrame的列,这是完全错误的!下图就是一个错误案例(行列搞反了):

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/152440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7、Javaweb_tomcatservlet

web相关概念 1. 软件架构 1. C/S&#xff1a;客户端/服务器端 2. B/S&#xff1a;浏览器/服务器端 2. 资源分类 1. 静态资源&#xff1a;所有用户访问后&#xff0c;得到的结果都是一样的&#xff0c;称为静态资源.静态资源可以直接被浏览器解析 * 如&am…

2023年最全盘点 | 16款跨平台应用程序开发框架

近年来小程序技术被微信及其生态应用带的如火如荼的&#xff0c;开发者的世界里&#xff0c;小程序的技术非常受关注&#xff0c;特别在流量承接及跨端开发方面&#xff0c;均受到不同规模的企业关注及积极实践。 2023年&#xff0c;小程序依然很火&#xff0c;但却有了一些不…

元宇宙产业委MCC|于佳宁:加密资产摆脱不了周期性规律

2022年&#xff0c;加密行业面临寒冬&#xff0c;加密货币市场总价值大量缩水&#xff0c;降逾1.45万亿美元&#xff0c;期间多家加密公司接连倒塌&#xff0c;引发市场连锁效应。 加密货币总市值降逾1.45万亿美元 根据CoinMarketCap数据&#xff0c;加密货币总市值(Total Cry…

【服务器数据恢复】某品牌DS系列服务器RAID5数据恢复案例

服务器数据恢复环境&#xff1a; 某单位一台某品牌DS系列服务器连接4个扩展柜&#xff1b; 50块磁盘组建两组RAID5&#xff0c;其中一组由27块磁盘组建的RAID5存放的是Oracle数据库文件&#xff1b; 上层一共划分11个卷。 服务器故障&#xff1a; 磁盘故障导致存放Oracle数据库…

JavaScript类和对象

1、面向对象与面向过程 1.1 面向过程编辑POP(Process-oriented programming) 面向过程就是分析出解决问题所需要的步骤&#xff0c;然后用函数把这些步骤一步一步实现&#xff0c;使用的时候再一个一个的依次调用就可以了。面向过程&#xff0c;就是按照我们分析好的步骤&…

20张图带你了解JVM运行时数据区

运行时数据区总览 内存是非常重要的系统资源&#xff0c;是硬盘和CPU的中间仓库及桥梁&#xff0c;承载着操作系统和应用程序的实时运行。JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策略&#xff0c;保证了JVM的高效稳定运行。不同的JVM对于内存的划分方式和管…

C 程序设计教程(11)—— 字符数据的输入与输出

C 程序设计教程&#xff08;11&#xff09;—— 字符数据的输入与输出 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用户阅读。 目录C 程序设计教程&#xff08;11&…

【2004NOIP普及组】T2.花生采摘 试题解析

【2004NOIP普及组】T2.花生采摘 试题解析 时间限制: 1000 ms 内存限制: 65536 KB 【题目描述】 鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!——熊字”。 鲁宾逊先生…

Android---Chip

Chip Chip 代表一个小块中的复杂实体&#xff0c;如联系人。它是一个圆形按钮&#xff0c;由一个标签&#xff0c;一个可选的芯片图标和一个可选的关闭图标组成。如果 Chip 可检查&#xff0c;则可以点击或切换Chip 。 style"style/Widget.MaterialComponents.Chip.Action…

疫情在家搭建的简单易学的SLAM建图机器人

1 简介 Easy_mqOS 是我仿照ROS 搭建的基于MQTT的简易机器人分布式开发框架,是一种轻量级并且十分容易上手的框架&#xff0c;支持多个节点的主题的订阅和单topic发布,节点之间独立、解耦合。没有复杂的文件配置&#xff0c;一定的make编程基础&#xff0c;像正常启动服务一样&a…

Redis未授权访问漏洞(四)SSH key免密登录

前言 系列文章 Redis未授权访问漏洞(一)先导篇 Redis未授权访问漏洞(二)Webshell提权篇 Redis未授权访问漏洞(三)Redis写入反弹连接定时任务 SSH key免密登录 实战实验 环境准备 实验前我们先来复习一遍ssh-key免密登录的流程 攻击机&#xff1a; Centos7 IP:192.168.142.44 靶…

局部变量的特点以及成员变量的区别

1. 概念在上面的章节中&#xff0c;其实已经跟大家介绍了局部变量的概念。即&#xff1a;局部变量是在定义形参、方法或代码块内部的变量&#xff0c;该变量只在当前方法、代码块中有效。2. 特点局部变量具有如下特点&#xff1a;● 局部变量声明在方法、构造方法或者代码块、形…

Mask RCNN网络源码解读(Ⅴ) --- Mask R-CNN论文解读环境配置以及训练脚本解析

目录 1.源码地址 2.项目配置 2.1 环境配置 2.2 文件结构 2.3 预训练权重下载地址&#xff08;下载后放入当前文件夹中&#xff09; 2.4 数据集&#xff1a;本例程使用的有COCO2017数据集和Pascal VOC2012数据集 2.4.1 COCO2017数据集 2.4.2 Pascal VOC2012数据集 2…

matplotlib+cartopy+geopandas,实现专业地图可视化!

知乎上有人问如何实现精细化地图&#xff1f;现有的excel、tableau、powerbi都只能套用有限的模板&#xff0c;是否有工具能实现高度定制化&#xff1f;除了专业的Gis软件外&#xff0c;我能想到相对完美的就是使用Python来实现。如果想制作出版级的地图可视化图表&#xff0c;…

《UEFI内核导读》UEFI Application Binary Interface (ABI)简介

敬请关注&#xff1a;“固件C字营 UEFI根据CPU体系结构和编译器的不同有着不同的“调用约定”统称之为“EFI ABI”。以MSVC和x86/x64举例来说&#xff0c;默认MSVC/x86使用 “C标准cdecl”&#xff0c;MSVC/x64使用“MSVC x64 ABI”。Gcc/x86使用“C标准cdecl”&#xff0c;Gc…

ESP-IDF:使用vector和deque容器进行打分排序例程

ESP-IDF实现例程&#xff1a; /5位选手&#xff0c;分别打十个分数&#xff0c;取中间8个分数&#xff0c;求平均值&#xff0c;然后根据选手的分数排序输出/ #include <stdio.h> #include using namespace std; #include #include #include #include class playe…

mongoDB原子操作事务

原子操作 原子操作&#xff08;atomic operation&#xff09;指的是由多步操作组成的一个操作。如果该操作不能原子地执行&#xff0c;则要么执行完所有步骤&#xff0c;要么一步也不执行&#xff0c;不可能只执行所有步骤的一个子集。不可中断的一个或者一系列操作, 也就是不…

Vue3——第三章(生命周期钩子)

一、setup() Vue3在组合式 API中去掉了在Vue3中的beforeCreate、created两个生命周期&#xff0c;使用setup()来顶替这两个生命周期。 二、onBeforeMount() 注册一个钩子&#xff0c;在组件被挂载之前被调用。当这个钩子被调用时&#xff0c;组件已经完成了其响应式状态的设…

国产电源芯片DP4054 软硬件兼容TP4054 规格书资料

DP4054 是一款完整的采用恒定电流/恒定电压单 节锂离子电池充电管理芯片。其SOT小封装和较少的外部元件数目使其成为便携式应用的理想器件&#xff0c;DP4054 可以适合USB 电源和适配器电源工作。跟进口的TP4054完全兼容&#xff0c;软硬件无需更改直接替换。 管脚配置 功能框…

(十六)一篇文章学会Java的常用API

目录 前言: 一、Object:toStringequals 二、StringBuilder 三、Math 四、System 五、BigDecimal 前言: API的主要目的是提供应用程序与开发人员以访问一组例程的能力&#xff0c;而又无需访问源码&#xff0c;或理解内部工作机制的细节。提供API所定义的功能的软件称作此API的实…