Python之Pandas库(1)——Pandas数据结构

本博客为《利用Python进行数据分析》的读书笔记,请勿转载用于其他商业用途。

1、Series

Series是一种一维的数组型对象,它包含了一个值序列,并且包含了数据标签,称为索引(index)。最简单的序列可以仅仅由一个数组形成:

import pandas as pd

obj = pd.Series([4, 7, -5, 3])
print(obj)

#
0    4
1    7
2   -5
3    3
dtype: int64

交互式环境中Series的字符串表示,索引在左边,值在右边。由于不为数据指定索引,默认生成的索引是从0到N-1(N是数据的长度)。我们可以通过values属性和index属性分别获得Series对象的值和索引:

print(obj.values)
print(obj.index)

#
[ 4  7 -5  3]
RangeIndex(start=0, stop=4, step=1)

通常需要创建一个索引序列,用标签标识每个数据点:

obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
print(obj2)
print(obj2.index)

#
d    4
b    7
a   -5
c    3
dtype: int64
Index(['d', 'b', 'a', 'c'], dtype='object')

与Numpy相比,我们可以在从数据中选择数据的时候使用标签来进行索引:

obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
print(obj2['a'])

obj2['d'] = 6
print(obj2[['c', 'a', 'd']])

#
-5
c    3
a   -5
d    6
dtype: int64

这里需要注意的是,我们在输出obj2索引为 c、a、d的值时,使用了2个中括号。['c', 'a', 'd']包含的不是数字而是字符串,作为索引列表。

使用Numpy的函数或Numpy风格的操作,比如使用布尔值数组进行过滤,与标量相乘,或是应用数学函数,这些操作将保存索引值链接:

obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
print(obj2[obj2 > 0])
print(obj2 * 2)
print(np.exp(obj2))

#
d    4
b    7
c    3
dtype: int64

d     8
b    14
a   -10
c     6
dtype: int64

d      54.598150
b    1096.633158
a       0.006738
c      20.085537
dtype: float64
从另一个角度考虑Series,可以认为它是一个长度固定且有序的字典,因为它将索引值的数据值按位置配对。
obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
print('b' in obj2)
print('e' in obj2)

#
True
False

如果已经有数据包含在Python字典中,可以使用字典生成一个Series:

sdata = {'Ohio':35000, 'Texas':71000, 'Oregon':16000, 'Utah':5000}
obj3 = pd.Series(sdata)
print(obj3)

#
Ohio      35000
Texas     71000
Oregon    16000
Utah       5000
dtype: int64

当把字典传递给Series构造函数时,产生的Series的索引将是排序好的字典键。可以将字典键按照想要的顺序传递给构造函数,从而使生成的Series的索引顺序符合预期:

sdata = {'Ohio':35000, 'Texas':71000, 'Oregon':16000, 'Utah':5000}
states = ['California', 'Ohio', 'Oregon', 'Texas']
obj4 = pd.Series(sdata, index=states)
print(obj4)

#
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64

 “NA”表示缺失数据。pandas中使用isnull和notnull来检查缺失数据:

print(pd.isnull(obj4))
print(pd.notnull(obj4))

#
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool

isnull和notnull也是Series的实例方法:

print(obj4.isnull())

#
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

Series对象自身和其索引都有name属性,这个特性与pandas其他重要功能集成在一起:

obj4.name = 'population'
obj4.index.name = 'states'
print(obj4)

#
states
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
Name: population, dtype: float64

Series的索引可以通过按位置赋值的方式进行改变:

obj = pd.Series([4, 7, -5, 3])
obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']
print(obj)

#
Bob      4
Steve    7
Jeff    -5
Ryan     3
dtype: int64

2、DataFrame

DataFrame表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被视为一个共享相同索引的Series的字典。在DataFrame中,数据被储存为一个以上的二维块,而不是列表、字典或其他一维数组的集合。

尽管DataFrame是二维的,但我们可以利用分层索引在DataFrame中展现更高维度的数据。分层索引是pandas中一种更为高级的数据处理特性。

有多种方式可以构建DataFrame,其中最常用的方式是利用包含等长度列表或Numpy数组的字典来形成DataFrame:

data = {'states': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
        'year': [2000, 2001, 2002, 2001, 2002, 2003],
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame = pd.DataFrame(data)
print(frame)

#
   states  year  pop
0    Ohio  2000  1.5
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9
5  Nevada  2003  3.2

产生的DataFrame会自动为Series分配索引,并且列会按照排序的顺序排列。对于大型DataFrame,head方法将会只选出头部的5行:

print(frame.head())

#
   states  year  pop
0    Ohio  2000  1.5
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9

如果指定了列的顺序,DataFrame的列将会按照指定顺序排列:

frame1 = pd.DataFrame(data, columns=['year', 'states', 'pop'])
print(frame1)

#
   year  states  pop
0  2000    Ohio  1.5
1  2001    Ohio  1.7
2  2002    Ohio  3.6
3  2001  Nevada  2.4
4  2002  Nevada  2.9
5  2003  Nevada  3.2

如果传的列不包含在字典中,将会在结果中出现缺失值:

frame2 = pd.DataFrame(data, columns=['year', 'states', 'pop', 'debt'],
                      index=['one', 'two', 'three', 'four', 'five', 'six'])
print(frame2)

#
       year  states  pop debt
one    2000    Ohio  1.5  NaN
two    2001    Ohio  1.7  NaN
three  2002    Ohio  3.6  NaN
four   2001  Nevada  2.4  NaN
five   2002  Nevada  2.9  NaN
six    2003  Nevada  3.2  NaN

DataFrame中的一列,可以按字典型标记或属性那样检索为Series:

print(frame2['states'])
print(frame2.year)

#
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
six      Nevada
Name: states, dtype: object

one      2000
two      2001
three    2002
four     2001
five     2002
six      2003
Name: year, dtype: int64

注意,返回的Series与原DataFrame有相同的索引,且Series的name属性也会被合理设置。行也可以通过为止或特殊属性loc进行选取:

print(frame2.loc['three'])

#
year      2002
states    Ohio
pop        3.6
debt       NaN
Name: three, dtype: object

列的引用是可以修改的,例如空的“debt”列可以赋值为标量值或数组值:

frame2['debt'] = 16.5
print(frame2)

#
       year  states  pop  debt
one    2000    Ohio  1.5  16.5
two    2001    Ohio  1.7  16.5
three  2002    Ohio  3.6  16.5
four   2001  Nevada  2.4  16.5
five   2002  Nevada  2.9  16.5
six    2003  Nevada  3.2  16.5
frame2['debt'] = np.arange(6)
print(frame2)

#
       year  states  pop  debt
one    2000    Ohio  1.5     0
two    2001    Ohio  1.7     1
three  2002    Ohio  3.6     2
four   2001  Nevada  2.4     3
five   2002  Nevada  2.9     4
six    2003  Nevada  3.2     5

当我们将列表或数组赋值给一个列时,值的长度必须和DataFrame的长度相匹配。如果我们将Series赋值给一列时,Series的索引将会按照DataFrame的索引重新排列,并在空缺的地方填充缺失值:

val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
frame2['debt'] = val
print(frame2)

#
       year  states  pop  debt
one    2000    Ohio  1.5   NaN
two    2001    Ohio  1.7  -1.2
three  2002    Ohio  3.6   NaN
four   2001  Nevada  2.4  -1.5
five   2002  Nevada  2.9  -1.7
six    2003  Nevada  3.2   NaN

如果被赋值的列并不存在,则会生成一个新的列。del关键字可以像在字典中那样对DataFrame删除列。

在del的例子中,我们首先增加一列,这一列时布尔值,判断条件是states列是否为‘Ohio’:

frame2['eastern'] = frame2.states == 'Ohio'
print(frame2)

#
       year  states  pop debt  eastern
one    2000    Ohio  1.5  NaN     True
two    2001    Ohio  1.7  NaN     True
three  2002    Ohio  3.6  NaN     True
four   2001  Nevada  2.4  NaN    False
five   2002  Nevada  2.9  NaN    False
six    2003  Nevada  3.2  NaN    False

注意:frame.eastern的语法无法创建新的列。

del方法可以用于移除之前新建的列:

del frame2['eastern']
print(frame2.columns)

#
Index(['year', 'states', 'pop', 'debt'], dtype='object')

注意:从DataFrame中选取的列是数据的视图,而不是拷贝。因此,对Series的修改会映射到DataFrame中。如果需要复制,则应当显式地使用Series的copy方法。

另一种常用的数据形式是包含字典的嵌套字典。如果嵌套字典被赋值给DataFrame,pandas会将字典的键作为列,将内部字典的键作为行显式:

pop = {'Nevada': {2001: 2.4, 2002: 2.9},
       'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
frame3 = pd.DataFrame(pop)
print(frame3)

#
      Nevada  Ohio
2001     2.4   1.7
2002     2.9   3.6
2000     NaN   1.5

可以将使用类似Numpy的语法对DataFrame进行转置操作(调换行和列):

print(frame3.T)

#
        2001  2002  2000
Nevada   2.4   2.9   NaN
Ohio     1.7   3.6   1.5

内部字典的键被联合、排序后形成了结果的索引。如果已经显式指明索引的话,内部字典的键将不会被排序:

print(pd.DataFrame(pop, index=[2001, 2002, 2003]))
#
      Nevada  Ohio
2001     2.4   1.7
2002     2.9   3.6
2003     NaN   NaN

包含Series的字典也可以用于构造DataFrame:

pdata = {'Ohio': frame3['Ohio'][:-1],
         'Nevada': frame3['Nevada'][:2]}
print(pd.DataFrame(pdata))

#
      Ohio  Nevada
2001   1.7     2.4
2002   3.6     2.9

和Series类似,DataFrame的values属性会将包含在DataFrame中的数据以二维ndarray的形式返回:

print(frame3.values)

#
[[2.4 1.7]
 [2.9 3.6]
 [nan 1.5]]

如果DataFrame的列是不同dtypes,则values的dtype会自动选择适合所有列的类型:

print(frame2.values)

#
[[2000 'Ohio' 1.5 nan]
 [2001 'Ohio' 1.7 nan]
 [2002 'Ohio' 3.6 nan]
 [2001 'Nevada' 2.4 nan]
 [2002 'Nevada' 2.9 nan]
 [2003 'Nevada' 3.2 nan]]

DataFrame构造函数的有效输入

类型

注释

2D ndarray

数据的矩阵,行和列的标签是可选参数

数组、列表和元组构成的字典

每个序列称为DataFrame的一列,所有的序列必须长度相等

NumPy结构化/记录化数组

与数组构成的字典一致

Series构成的字典

每个值称为一列,每个Series的索引联合起来形成结果的行索引,也可以显式地传递索引

字典构成的字典

每一个内部字典称为一列,键联合起来形成结果的行索引

字典或Series构成的列表

列表中的一个元素形成DataFrame的一行,字典键或Series索引联合起来形成DataFrame的列标签

列表或元组构成的列表

与2D ndarray的情况一致

其他DataFrame 如果不显示传递索引,则会使用原DataFrame的索引 NumPy MaskedArray 与2D ndarray的情况类似,但隐蔽值会在结果DataFrame中称为NA/缺失值

3、索引对象

pandas中的索引对象是用于储存轴标签和其他元数据的。在构造Series或DataFrame时,我们所使用的任意数组或标签都可以在内部转换为索引对象:

obj = pd.Series(range(3), index=['a', 'b', 'c'])
index = obj.index
print(obj)
print(index)
print(index[1:])

#
a    0
b    1
c    2
dtype: int64
Index(['a', 'b', 'c'], dtype='object')
Index(['b', 'c'], dtype='object')

索引对象是不可改变的,因此用户是无法修改索引对象的。不变性是的在多种数据结构中分享索引对象更为安全:

labels = pd.Index(np.arange(3))
print(labels)

obj2 = pd.Series([1.5, -2.5, 0], index=labels)
print(obj2)

print(obj2.index is labels)

#
Int64Index([0, 1, 2], dtype='int64')

0    1.5
1   -2.5
2    0.0
dtype: float64

True

一些用户并不经常利用索引对象提供的功能,但是因为一些操作会产生包含索引化数据的结果,理解索引如何工作还是很重要的。

一些索引对象的方法和属性
方法 描述
append 将额外的索引对象粘贴到原索引后,产生一个新的索引
difference 计算两个索引的差集
intersection 计算两个索引的交集
union 计算两个索引的并集
isin 计算表示每一个值是否在传值容器中的布尔数组
delete 将位置i的元素删除,并产生新的索引
drop 根据传参删除指定索引值,并产生新的索引
insert 在位置i插入元素,并产生新的索引
is_monotonic 如果索引序列递增则返回True
is_unique 如果索引序列唯一则返回True
unique 计算索引的唯一序列值
发布了27 篇原创文章 · 获赞 9 · 访问量 986

猜你喜欢

转载自blog.csdn.net/sinat_42574069/article/details/104033781
今日推荐