pandas数据结构
Pandas 是基于NumPy 的一种强大的分析结构化数据的工具,可以从各种文件格式比如CSV、Excel、JSON、SQL导入数据。Pandas提供了大量能使我们快速便捷处理数据的函数和方法,可以对各种数据进行运算操作,比如归并、再成形、选择,还有数据清洗和数据加工特征。被广泛应用在学术、金融、统计学等各个数据分析领域。熟练并掌握pandas常规用法是正确构建机器学习模型的第一步。
pandas两大核心数据结构:Series和DataFrame。
维数 | 名称 | 描述 | 数据表 |
---|---|---|---|
1 | Series | 带标签的一维同构数组 | 一列或一行 |
2 | DataFrame | 带标签的,大小可变的,二维异构表 | 一个sheet表或一个table |
- Series是一种一维数据结构,每一个元素都带有一个索引,其中索引可以为数字或字符串。其基本数据结构包括索引列和单列的数据列。
- Dataframe是一种二维数据结构,数据以表格形式(与excel类似)存储,有对应的行和列。其基本数据结构为索引列和多列数据。
Pandas 数据结构就像是低维数据的容器。比如,DataFrame 是 Series 的容器,Series 则是标量的容器。使用这种方式,可以在容器中以字典的形式插入或删除对象。
1. Series
Series是一个带有名称和索引的一维数组,在Series中包含的数据类型可以是整数、浮点、字符串、Python对象等,这一点与Python中的列表比较类似,但与列表不同的是,列表只能通过数字索引取值,而Series可以通过自定义索引取值,从这一点来看Series与字典类似。
Series是由相同元素类型构成的一维数据结构。由数据列data、索引列index、数据类型dtype组成。其中,索引列也可以指定名称,默认为空。
Series特点:
- Series每一个元素都带有一个索引index;
- 与一维数组的含义相似,Pandas 默认用0到n-1来作为Series的索引index, 也可以指定index为其他数字或字符串,可以把index理解为字典的键;
- 索引在左边,数据在右边。
创建series
Series 的创建方式如下:
pandas.Series(data=None, index=None, dtype=None, name=None, copy=False)
参数说明:
- data:可以是python对象、numpy的ndarray、一个标量。
- index:数据索引标签,和data的长度相同,如果不指定默认从0开始。
- dtype:数据类型。
- name:设置名称。
- copy:拷贝数据,默认为 False。
通常创建Series时只需要指定前两个参数:data和index,若不需要指定index,该参数也可以省略用默认index:0-n
data无索引
- 如果data为 ndarray(1D)或list(1D),那么其缺少Series需要的索引信息,如果不提供index,那么其将生成默认数值索引 range(0, data.shape[0])。
import numpy as np
import pandas as pd
pd.__version__
'2.0.1'
arr1 = np.random.randint(10,size=5)
arr1
array([1, 8, 7, 2, 8])
pd.Series(arr1)
0 1
1 8
2 7
3 2
4 8
dtype: int32
可以看出索引默认是0到数据长度-1。
- 如果提供 index,则index必须和data长度相同;
index1 = list('abcde')
index1
['a', 'b', 'c', 'd', 'e']
s1 = pd.Series(arr1,index1) #在这里传递了索引值。现在可以在输出中看到自定义的索引值。
s1
a 3
b 2
c 7
d 6
e 7
dtype: int32
将生成的列表作为索引参数,生成的Series的索引即为列表对应的元素。我们可以把上述代码简化如下:
s2 = pd.Series(
data = np.random.randint(10,size=5),
index = list('abcde')
)
s2
a 4
b 7
c 0
d 4
e 8
dtype: int32
s2[0:3]
a 4
b 7
c 0
dtype: int32
s2['a':'d']
a 4
b 7
c 0
d 4
dtype: int32
data有索引
- 如果 data 为 Series 或 dict ,则本身提供了Series需要的索引信息,所以 index 项不需要再提供;
dict1 = {'a':1,'b':2,'c':3}
pd.Series(dict1)
a 1
b 2
c 3
dtype: int64
- 如果额外指定了index项,那么其将对当前构建的Series进行重索引(以当前index为准,如果旧索引没有,则值为NaN)(等同于重索引reindex操作)。
index2 = ['a','b','d']
s3 = pd.Series(data=dict1, index=index2)
s3
a 1.0
b 2.0
d NaN
dtype: float64
缺失项填充NaN(NaN:not a number为pandas缺失值标记)。
若data 是标量值时,必须提供索引。Series 按索引长度重复该标量值。
pd.Series(5.)
0 5.0
dtype: float64
Series常用属性介绍:
-
Series.index 索引(轴标签)
-
Series.values 根据 dtype 将数据值作为 ndarray返回
-
Series.dtype 返回Series数据的 dtype 对象
-
Series.shape 返回Series形状的元组。
-
Series.size 返回元素数。
-
Series.hasnans 返回是否有缺失值
s2.index #索引属性
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
s2.values #数据值属性
array([4, 7, 1, 6, 0])
s2.dtype #元素类型属性
dtype('int32')
s2.shape #形状属性
(5,)
s2.size #元素个数属性
5
s2.hasnans #是否有空元素属性
False
s3.hasnans #存在缺失值的Series则返回True
True
对于一个Series,其中最常用的属性为值(values),索引(index),名字(name),类型(dtype)。
通过列表构建Series
mylist = list('abcedf') # 列表
print(mylist)
['a', 'b', 'c', 'e', 'd', 'f']
# 从list构造series 由于没有为数据指定索引,于是会⾃动创建⼀个0到N-1(N为数据的⻓度)的整数型索引。
ser1 = pd.Series(mylist)
print(ser1)
0 a
1 b
2 c
3 e
4 d
5 f
dtype: object
ser1.index
RangeIndex(start=0, stop=6, step=1)
如果数据是ndarray,则传递的索引必须具有相同的长度。 如果没有传递索引值,那么默认的索引将是范围(n),其中n是数组长度,即[0,1,2,3…. range(len(array))-1] - 1]。
2. dataframe
dataframe是一种二维数据结构,数据以表格形式(与excel类似)存储,有对应的行和列。dataframe结构名称:
- 每列可以是不同的值类型(数值、字符串、布尔值等)
- 既有行索引index,也有列索引columns
- 可以被看做由Series组成的字典(共⽤同⼀个索引)
虽然DataFrame是以⼆维结构保存数据的,但仍然可通过层次化索引的表格型结构来表示更⾼维度的数据,这是pandas中许多⾼级数据处理功能的关键要素
处理 DataFrame 等表格数据时,index(行)或 columns(列)比 axis 0 和 axis 1 更直观。用这种方式迭代 DataFrame 的列,代码更易读易懂:
创建DataFrame
pd.DataFrame(data=None, index=None, columns=None)
data无行索引index,无列索引columns
如果 data 为 ndarray(2D) or list(2D) ,那么其缺少 DataFrame 需要的行、列索引信息
data1 = np.random.randint(10,size=(2,3))
data1
array([[7, 0, 6],
[3, 0, 7]])
- 如果不提供 index 或 columns 项,那么其将默认生成数值索引range(0, data.shape[0])) 或 range(0, data.shape[1])
df = pd.DataFrame(data1)
df
0 | 1 | 2 | |
---|---|---|---|
0 | 7 | 0 | 6 |
1 | 3 | 0 | 7 |
df[0]
0 7
1 3
Name: 0, dtype: int32
- 如果提供 index 或 columns 项,其必须和data的行 或 列长度相同,否则报错
index1 = ['a','b'] #两个索引表示两行,对应两行数据
col1 = ['A','B','C'] #三个列,对应三列数据
pd.DataFrame(data=data1, index=index1, columns=col1)
A | B | C | |
---|---|---|---|
a | 6 | 4 | 0 |
b | 4 | 0 | 6 |
可以只提供index或column,没提供的就用默认的
pd.DataFrame(data=data1, columns=col1)
A | B | C | |
---|---|---|---|
0 | 6 | 4 | 0 |
1 | 4 | 0 | 6 |
data无行索引index,有列索引columns
- 如果data为 dict of (ndarray(1D) or list(1D)) ,即字典的值是Numpy或列表形式,所有ndarray或list的长度必须相同。dict的key为DataFrame提供了需要的columns信息,缺失index;
- 如果提供 index 项,必须和list的长度相同。
data2 = { 'A' : [1,4], 'B': [2,5], 'C':[3,6] } #字典的键作为列索引columns,字典的值是长度为2的列表形式
index2 = ['a','b'] #index的长度与字典的值列表长度相同
pd.DataFrame(data=data2, index=index2)
A | B | C | |
---|---|---|---|
a | 1 | 2 | 3 |
b | 4 | 5 | 6 |
- 如果不提供 index,那么其将默认生成数值索引range(0, data.shape[0]));
pd.DataFrame(data=data2)
A | B | C | |
---|---|---|---|
0 | 1 | 2 | 3 |
1 | 4 | 5 | 6 |
data有行索引index,有列索引columns
如果data为 dict of (Series or dict) ,那么其已经提供了DataFrame需要的所有信息;
如果多个Series或dict间的索引不一致,那么取并操作(pandas不会试图丢掉信息),缺失的数据填充NaN;
data3 = { 'A' : { 'a':1, 'b':4}, 'B': {'a':2,'b':5}, 'C':{'a':3, 'c':6} }
pd.DataFrame(data=data3)
A | B | C | |
---|---|---|---|
a | 1.0 | 2.0 | 3.0 |
b | 4.0 | 5.0 | NaN |
c | NaN | NaN | 6.0 |
上述代码是字典嵌套数据,外层键对应的值仍为字典形式,外层键对应生成df的列索引columns,而里层键对应生成df的行索引index。
创建一个dataframe用于表示学生信息
data = {'姓名': ['甲一', '乙二', '丙三', '丁四', '张三', '李四', '王五','赵六'],
'学号': [50, 51, 52, 53, 54, 55, 56, 57],
'出生日期': ['2001年1月1日','1999年2月2日','2002年3月3日','2000年4月4日',
'2001年5月5日','2000年6月6日','1999年7月7日','2001年8月8日'],
'年龄': [19, 21, 18, 20, 19, 20, 21,19],
'籍贯': ['福田','龙岗','宝安','龙岗','南山','宝安','龙岗','福田'],
'linux技术成绩': [92, 95, 85., 80, 88, 90, 82,98],
'python基础成绩': [90, 88, 91, 78, 83, 95, 75,93]}
df = pd.DataFrame(data)
df
姓名 | 学号 | 出生日期 | 年龄 | 籍贯 | linux技术成绩 | python基础成绩 | |
---|---|---|---|---|---|---|---|
0 | 甲一 | 50 | 2001年1月1日 | 19 | 福田 | 92.0 | 90 |
1 | 乙二 | 51 | 1999年2月2日 | 21 | 龙岗 | 95.0 | 88 |
2 | 丙三 | 52 | 2002年3月3日 | 18 | 宝安 | 85.0 | 91 |
3 | 丁四 | 53 | 2000年4月4日 | 20 | 龙岗 | 80.0 | 78 |
4 | 张三 | 54 | 2001年5月5日 | 19 | 南山 | 88.0 | 83 |
5 | 李四 | 55 | 2000年6月6日 | 20 | 宝安 | 90.0 | 95 |
6 | 王五 | 56 | 1999年7月7日 | 21 | 龙岗 | 82.0 | 75 |
7 | 赵六 | 57 | 2001年8月8日 | 19 | 福田 | 98.0 | 93 |
- 由于没有提供行索引index,DataFrame会⾃动加上索引(跟Series⼀样)。
dataframe属性:
由于dataframe有多列,并且每列的数据类型可以不同,dataframe的常用属性更多,包括:
- dataframe.index 行索引
- dataframe.columns 列索引
- dataframe.values 返回 DataFrame 的 Numpy 表示
- dataframe.dtypes 返回DataFrame各列的数据类型
- dataframe.shape 返回一个表示 DataFrame 维度的元组
- dataframe.size 返回元素数。
- dataframe.info 打印 DataFrame 的简明摘要
- dataframe.axes 返回表示 DataFrame 行列索引
- dataframe.ndim 返回一个表示轴数/数组维数
df.index
RangeIndex(start=0, stop=8, step=1)
df.columns
Index(['姓名', '学号', '出生日期', '年龄', '籍贯', 'linux技术成绩', 'python基础成绩'], dtype='object')
values属性以⼆维ndarray的形式返回DataFrame中的数据:
df.values
array([['甲一', 50, '2001年1月1日', 19, '福田', 92.0, 90],
['乙二', 51, '1999年2月2日', 21, '龙岗', 95.0, 88],
['丙三', 52, '2002年3月3日', 18, '宝安', 85.0, 91],
['丁四', 53, '2000年4月4日', 20, '龙岗', 80.0, 78],
['张三', 54, '2001年5月5日', 19, '南山', 88.0, 83],
['李四', 55, '2000年6月6日', 20, '宝安', 90.0, 95],
['王五', 56, '1999年7月7日', 21, '龙岗', 82.0, 75],
['赵六', 57, '2001年8月8日', 19, '福田', 98.0, 93]], dtype=object)
df.dtypes
姓名 object
学号 int64
出生日期 object
年龄 int64
籍贯 object
linux技术成绩 float64
python基础成绩 int64
dtype: object
df.shape
(8, 7)
df.size
56
df.info
<bound method DataFrame.info of 姓名 学号 出生日期 年龄 籍贯 linux技术成绩 python基础成绩
0 甲一 50 2001年1月1日 19 福田 92.0 90
1 乙二 51 1999年2月2日 21 龙岗 95.0 88
2 丙三 52 2002年3月3日 18 宝安 85.0 91
3 丁四 53 2000年4月4日 20 龙岗 80.0 78
4 张三 54 2001年5月5日 19 南山 88.0 83
5 李四 55 2000年6月6日 20 宝安 90.0 95
6 王五 56 1999年7月7日 21 龙岗 82.0 75
7 赵六 57 2001年8月8日 19 福田 98.0 93>
df.axes #行列索引名称
[RangeIndex(start=0, stop=8, step=1),
Index(['姓名', '学号', '出生日期', '年龄', '籍贯', 'linux技术成绩', 'python基础成绩'], dtype='object')]
df.ndim
2
df['姓名']
0 甲一
1 乙二
2 丙三
3 丁四
4 张三
5 李四
6 王五
7 赵六
Name: 姓名, dtype: object
type(df['姓名'])
pandas.core.series.Series
详细参考:
Series官方文档:https://pandas.pydata.org/pandas-docs/stable/reference/series.html
DataFrame官方文档:https://pandas.pydata.org/pandas-docs/stable/reference/frame.html