【数据处理包Pandas】Series的创建与操作


一、引入Pandas进行数据处理的必要性

  NumPy 通过把大量同类数据组织成 ndarray 数组对象,并引入可以支持逐元素操作和广播机制的通用函数,为数值计算提供了许多不可或缺的功能。但当需要处理更灵活的数据任务(如为数据添加标签、处理缺失值等),或者需要做一些不是对每个元素都进行广播映射的计算(如分组、透视表等)时,NumPy 的限制就非常明显了。

  建立在 NumPy 数组结构上的 Pandas 库,为常见的各种数据处理任务提供了捷径。Pandas 有三个基本对象:Series、DataFrame 和 Index。其中,Series 和 DataFrame 是 Pandas 中最常用的两个对象,分别对应于一维和二维数据的处理(Pandas 还有对三维甚至多维数据处理的 Panel 对象,但不太常用)。而 Index 对象则用于为数据建立索引以方便数据操作。

  Pandas(Python Data Analysis Library)是基于是基于 NumPy 的数据分析模块,它提供了大量标准数据模型和高效操作大型数据集所需的工具,可以说 Pandas 是使得 Python 能够成为高效且强大的数据分析环境的重要因素之一。

  Pandas 的三种数据结构:Series、DataFrame 和 Panel。Series 类似于一维数组;DataFrame 是类似表格的二维数组;Panel 可以视为 Excel 的多表单 Sheet。

导入方式:import pandas as pd

# 引入Numpy和Pandas库
import numpy as np
import pandas as pd

二、创建Series对象

Series 对象是一个带索引的一维数组,可以基于以下对象来创建:
Python列表、Python字典、一维ndarray数组对象、甚至一个标量

(一)通过列表创建Series

基于列表创建,索引是从0开始的整数,这属于隐式索引——自动添加的整数索引。

# 基于列表创建
data = pd.Series([0.25, 0.5, 0.75, 1.0])
data

输出结果:

0    0.25
1    0.50
2    0.75
3    1.00
dtype: float64

(二)通过字典创建Series

基于字典创建,索引是排好序的字典的键,也属于隐式索引——字典的键作为索引。

# 基于字典创建
score = pd.Series({'s03':87,'s02':68,'s01':92})
score

注意:字典的键值对是无序的,但 Series 对象的索引是有序的!

输出结果:

s01    92
s02    68
s03    87
dtype: int64

(三)通过一维数组创建Series

基于一维数组创建,创建的同时可以指定索引,显式索引——明确用index参数指定索引。

# 基于一维数组创建
rd = pd.Series(np.random.randint(0,10,5),index=['a','b','c','d','c'])
rd

注意:索引由有序、允许重复并且不可变的数据构成!

输出结果:

a    2
b    8
c    9
d    2
c    9
dtype: int32

(四)通过一个标量创建Series

基于一个标量创建,该标量会重复填充到每个索引上。

# 基于一个标量创建
pd.Series(5,index=[100,200,300])

说明 Series 元素的个数是由索引个数而非数据的个数决定的。

输出结果:

100    5
200    5
300    5
dtype: int64

(五)pd.Series函数的原型

pd.Series(data=None, index=None, dtype=None, name=None, copy=False)

参数说明:

  • data:提供数据的列表、字典、一维数组或单个标量。
  • index:允许指定索引。如果不指定就用从0开始的整数作为隐式索引(或位置索引),指定了就是显式索引(或标签索引);注意:索引由有序、允许重复并且不可变的数据构成!
  • dtype:允许指定元素类型。如果元素类型不一致,则会统一转化成 object 类型。

1、创建时如果是不同类型的数据,则会统一转化为 object 类型

# 创建时如果是不同类型的数据,则会统一转化为object类型
tp1 = pd.Series([0.25, '0.5', 0.75, 1.0])
tp1

输出结果:

0    0.25
1     0.5
2    0.75
3       1
dtype: object

2、创建时如果与dtype参数指定的类型不一致,可能存在类型转换

# 创建时如果与dtype参数指定的类型不一致,可能存在类型转换
tp2 = pd.Series([0.25, '0.5', 0.75, 1.0], dtype='float64')
tp2

输出结果:

0    0.25
1    0.50
2    0.75
3    1.00
dtype: float64

三、Series对象的属性

每个 Series 对象由两个数组构成:

  • index数组:它是从 ndarray 数组继承的 Index 索引对象,保存索引信息。
  • values:保存元素值的 ndarray 数组。

1、位置索引

data.index  # 位置索引

输出结果:

RangeIndex(start=0, stop=4, step=1)
data.values

输出结果:

array([ 0.25,  0.5 ,  0.75,  1.  ])

2、标签索引,注意字符串被表示成了object类型

score.index  # 标签索引,注意字符串被表示成了object类型

输出结果:

Index(['s01', 's02', 's03'], dtype='object')
score.values

输出结果:

array([92, 68, 87], dtype=int64)

最好使用标签索引而非位置索引,前者属于显式索引,后者是隐式索引。

Python 之禅第二条:显式优于隐式(Explicit is better than implicit)!

# import this查看Python之禅的内容
import this

输出结果:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

还可以对 Series 对象和 Index 对象分别命名,例如:

score.name = 'score of students'
score.index.name = 'sno'
score

输出结果:

sno
s01    92
s02    68
s03    87
Name: score of students, dtype: int64

四、Series对象的基本操作

(一)Series对象看作一维的Numpy数组

基于位置索引的切片,不包含终值;基于标签索引的切片,包含终值。

print(data[2])  # 用位置索引访问单个元素
print(score['s02'])  # 用标签索引访问单个元素
print("********************")
print(score[1:2])  # 基于位置索引的切片,不包含终值
print(score['s01':'s02'])  # 基于标签索引的切片,却包含终值

输出结果:

0.75
68
********************
sno
s02    68
Name: score of students, dtype: int64
sno
s01    92
s02    68
Name: score of students, dtype: int64

使用布尔数组做索引和使用花式索引(整数列表),得到的仍是Series对象。

print(score[score>85])  # 使用布尔数组做索引,得到的仍是Series对象
print(data[[2,0,1]])  # 使用花式索引(整数列表),得到的仍是Series对象

输出结果:

sno
s01    92
s03    87
Name: score of students, dtype: int64
2    0.75
0    0.25
1    0.50
dtype: float64

(二)Series对象看作特殊的字典

用键访问对应的值:字典不存在切片操作,因此切片操作是把 Series 对象看成 Numpy 而非字典。
通过键来返回 Series 的索引值,这种方法不建议,最好用score.index属性来得到索引值。

print(score['s02'])  # 用键访问对应的值(字典不存在切片操作,因此切片操作是把Series对象看成Numpy而非字典)
print(score.get('s03',0))  # 通过get函数访问键对应的值
print(list(score.items())) # 返回键值对
score.keys()  # 通过键来返回Series的索引值,这种方法不建议,最好用score.index属性来得到索引值

注意:字典的values()方法在此处不存在,要得到 Series 的数据值,应该使用score.values属性。

输出结果:

  68
  87
  [('s01', 92), ('s02', 68), ('s03', 87)]
  
  Index(['s01', 's02', 's03'], dtype='object', name='sno')

只有出现在索引中的键值对才会保留在 Series 对象中。

score2 = pd.Series({'s01':72,'s02':90,'s03':83,'s04':88,'s05':69}, index=['s05','s01','s03'])
score2

注意:结果按索引指定的顺序显示,而非按索引值的排序显示。

输出结果:

s05    69
s01    72
s03    83
dtype: int64

结论:Series 对象中元素的个数和元素排列顺序完全由其索引来决定。

若把参数index改为index=['s01','s03','s05','s06']

score22 = pd.Series({'s01':72,'s02':90,'s03':83,'s04':88,'s05':69}, index=['s01','s03','s05','s06']) 
score22

输出结果:

s01    72.0
s03    83.0
s05    69.0
s06     NaN
dtype: float64

由此可见,当标签不存在时,默认以NaN填充。

对两个 Series 对象运算时,Pandas 会按标签对齐元素,即标签相同的两元素进行计算。
当某一方的标签不存在时,默认以NaN(Not a Number)填充。由于NaN是一个特殊的浮点数,因此结果对象的元素被转换为float64类型。自动对齐标签是一个非常有用的功能。

total = score+score2
total

输出结果:

s01    159.0
s02      NaN
s03    175.0
s05      NaN
dtype: float64

(三)Series对象的增删改

1、增加

# 增加多个值需要借助于一个新的Series对象
more = pd.Series([89,93],index=['s06','s07'])
print(more)
score2 = score2.append(more)   # 注意:老版本是score2.append(more),但3.7版本之后都使用赋值语句的形式
print(score2)
# 增加一个值只要利用赋值操作即可,相当于字典的用法
score2['s08']=62
score2

输出结果:

s06    89
s07    93
dtype: int64
s01    72
s03    83
s05    69
s06    89
s07    93
dtype: int64

s01    72
s03    83
s05    69
s06    89
s07    93
s08    62
dtype: int64

2、删除

(1)使用del删除

# del直接原地删除一行
del score2['s08']  # 看成字典
print(score2)

输出结果:

s01    72
s03    83
s05    69
s06    89
s07    93
dtype: int64

(2)使用drop删除

# 更多使用drop删除,可以一次删除多行
score3 = score2.drop(['s06','s07'])  # 不是原地删除,score2保持不变
print(score2)  
print(score3)
score2.drop(['s06','s07'],inplace=True)  # 原地删除,score2改变
print(score2)  

输出结果:

s01    72
s03    83
s05    69
s06    89
s07    93
dtype: int64
s01    72
s03    83
s05    69
dtype: int64
s01    72
s03    83
s05    69
dtype: int64

3、改和查

# 改和查:需要利用索引,然后直接赋值
score2['s05'] = 80
print(score2)
print(score2.loc['s03'])

输出结果:

s01    72
s03    83
s05    80
dtype: int64
83
  • 37
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Francek Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值