利用python进行数据分析(十五)

第五章 pandas入门

锣鼓喧天,鞭炮齐鸣,终于第五章了。

pandas支持大部分NumPy语言风格的数组计算,尤其是数组函数以及没有for循环的各种数据处理。尽管pandas采用了很多NumPy的代码风格,但最大的不同在于pandas是用来处理表格型或异质型数据的,而NumPy更适合处理同质型的数值数组数据

使用前先导入pandas模块:

>>>import pandas as pd

5.1 pandas数据结构介绍

pandas含有两个最常用的数据结构:SeriesDataFrame

5.1.1 Series

Series是一种一维的数组型对象,它包含一个值序列(与NumPy中的类型相似),并且包含了数据标签,称为索引

最简单的序列可以仅仅由一个数组组成:

>>>obj = pd.Series([5, 6, -7, -8])
>>>obj
0    5
1    6
2   -7
3   -8
dtype: int64

左边的是索引,右边的是值,当我们不为数据指定索引时,默认生成的是0到N-1(N为数据长度)。可以通过values属性和index属性分别获得Series对象的值和索引:

#obj的值是一个一维数组
>>>obj.values
array([ 5,  6, -7, -8], dtype=int64)
#obj的索引与range(4)类似
>>>obj.index
RangeIndex(start=0, stop=4, step=1)

我们也可以创建一个索引序列,为每个数据添加一个标签:

>>>obj2 = pd.Series([5, 6, -7, -8], index=['b', 'd', 'c', 'a'])
>>>obj2
b    5
d    6
c   -7
a   -8
dtype: int64

这时候,我们可以在选择数据时使用标签来进行索引

>>>obj2['a']
-8
>>>obj2[['a', 'b', 'c']]
a   -8
b    5
c   -7
dtype: int64

Series数据同样可以使用NumPy函数或NumPy风格的操作,比如使用布尔值数组进行过滤,与标量相乘或者应用数学函数,这些操作仍然会保留索引值:

>>>obj2[obj2 > 0]
b    5
d    6
dtype: int64
>>>obj2 / 2
b    2.5
d    3.0
c   -3.5
a   -4.0
dtype: float64
>>>np.sum(obj2)
-4
>>>np.exp(obj2)
b    148.413159
d    403.428793
c      0.000912
a      0.000335
dtype: float64

从另一方面考虑Series,其实它相当于是一个长度固定且有序的字典,它的索引值与数据值是按位置配对的,在可能使用字典的上下文中,也可以使用Series

>>>'b' in obj2
True
>>>'f' in obj2
False

同样的,如果我们的数据保存在字典中,可以用字典生成一个Series

>>>citys = {'JiNan':1234, 'Taian':4352, 'QingDao':9172, 'YanTai':1329}
>>>obj3 = pd.Series(citys)
>>>obj3
JiNan      1234
Taian      4352
QingDao    9172
YanTai     1329
dtype: int64

当将一个字典传递给Series时,产生的Series的索引值是排序好的字典键,我们可以将字典的键按我们希望的顺序传递给构造函数,从而使Series的索引符合我们的预期:

>>>city = ['Taian', 'JiNan', 'QingDao', 'WeiHai']
>>>obj4 = pd.Series(citys, index=city)
>>>obj4
Taian      4352.0
JiNan      1234.0
QingDao    9172.0
WeiHai        NaN
dtype: float64

上面的例子中,因为’WeiHai’没有出现在字典的键中,因此它在Series中对应的是NaN,这是pandas标记缺失值的方法。同时,因为’YanTai’不在city中,所以在Series中它被排除了。

通常在数据分析中使用术语‘缺失’或者‘NA’表示缺失数据,在pandas中使用isnull(是缺失)和notnull(不是缺失)函数来检查缺失数据:

>>>pd.isnull(obj4)
Taian      False
JiNan      False
QingDao    False
WeiHai      True
dtype: bool
>>>pd.notnull(obj4)
Taian       True
JiNan       True
QingDao     True
WeiHai     False
dtype: bool

同时,isnullnotnull也是pandas的实例方法:

obj4.isnull()
Taian      False
JiNan      False
QingDao    False
WeiHai      True
dtype: bool

自动对齐索引Series的一个非常有用的特性,类似于合并数据,但仅仅是将在两个Series中都存在的数据对齐了,而

>>>obj3
JiNan      1234
Taian      4352
QingDao    9172
YanTai     1329
dtype: int64
>>>obj4
Taian      4352.0
JiNan      1234.0
QingDao    9172.0
WeiHai        NaN
dtype: float64
>>>obj3 + obj4
JiNan       2468.0
QingDao    18344.0
Taian       8704.0
WeiHai         NaN
YanTai         NaN
dtype: float64

Series对象自身和其索引都有name属性。

>>>obj4.name = 'population'
>>>obj4.index.name = 'city'
>>>obj4
city
Taian      4352.0
JiNan      1234.0
QingDao    9172.0
WeiHai        NaN
Name: population, dtype: float64

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

>>>obj
0    5
1    6
2   -7
3   -8
dtype: int64
>>>obj.index = ['z', 'x', 'c', 'v']
>>>obj
z    5
x    6
c   -7
v   -8
dtype: int64

5.1.2 DataFrame

`DataFrame是表示矩阵的数据表,它包含已排序的序列集合``,每一列可以是不同的值类型(数值,字符串,布尔值等)。

DataFrame既有行索引也有列索引,可以被视为一个共享相同索引的Series字典

DataFrame的数据被存储为一个以上的二维块,而不是列表、字典或者奇特一维数组的集合。

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

data = {'city': ['Jinan', 'jinan', 'jinan', 'qingdao', 'qingdao', 'qingdao'], 
        'year': [2018, 2019, 2020, 2018, 2019, 2020], 
        'pop': ['1.5', '1.7', '3.6', '2.4', '2.0', '3.2']}
>>>frame = pd.DataFrame(data)
>>>frame
      city  year  pop
0    Jinan  2018  1.5
1    jinan  2019  1.7
2    jinan  2020  3.6
3  qingdao  2018  2.4
4  qingdao  2019  2.0
5  qingdao  2020  3.2

产生的DataFrame会自动为Series分配索引并按排序的顺序排序,如果指定了顺序,则DataFrame会按照指定顺序排列,如果传入的列不在字典中,则会出现缺失值:

>>>pd.DataFrame(data, columns=['year', 'city', 'pop', 'debt'])
   year     city  pop debt
0  2018    Jinan  1.5  NaN
1  2019    jinan  1.7  NaN
2  2020    jinan  3.6  NaN
3  2018  qingdao  2.4  NaN
4  2019  qingdao  2.0  NaN
5  2020  qingdao  3.2  NaN

同样的,可以指定DataFrame的索引值:

>>>frame2 = pd.DataFrame(data, columns=['year', 'city', 'pop', 'debt'], 
                             index=['one', 'two', 'three', 'four', 'five', 'six'])
#‘行名’和‘列名’都有了,看上去像一个数据表了                             
>>>frame2
       year     city  pop debt
one    2018    Jinan  1.5  NaN
two    2019    jinan  1.7  NaN
three  2020    jinan  3.6  NaN
four   2018  qingdao  2.4  NaN
five   2019  qingdao  2.0  NaN
six    2020  qingdao  3.2  NaN

DataFrame中的一列可以按字典型标记或者属性那样检索为Series,要注意的是:frame2[colunm]对于任意列名均有效,但是frame2.colunm只有在列名是有效地pytho变量时有效。

>>>frame2['city']
one        Jinan
two        jinan
three      jinan
four     qingdao
five     qingdao
six      qingdao
Name: city, dtype: object
>>>frame2.year
one      2018
two      2019
three    2020
four     2018
five     2019
six      2020
Name: year, dtype: int64

DataFrame中的行可以通过位置或特殊属性loc进行选取,返回一行数据组成的Series

>>>frame2.loc['three']
year     2020
city    jinan
pop       3.6
debt      NaN
Name: three, dtype: object

当然,DataFrame中列的引用是可以修改的,我们可以给空的debt列赋值为标量值或者值数组:

>>>frame2['debt'] = np.arange(6.)
>>>frame2
       year     city  pop  debt
one    2018    Jinan  1.5   0.0
two    2019    jinan  1.7   1.0
three  2020    jinan  3.6   2.0
four   2018  qingdao  2.4   3.0
five   2019  qingdao  2.0   4.0
six    2020  qingdao  3.2   5.0

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

>>>val = pd.Series([-1.2, -1.5, -6.6], index=['three', 'five', 'six'])
>>>frame2['debt'] = val
frame2
       year     city  pop  debt
one    2018    Jinan  1.5   NaN
two    2019    jinan  1.7   NaN
three  2020    jinan  3.6  -1.2
four   2018  qingdao  2.4   NaN
five   2019  qingdao  2.0  -1.5
six    2020  qingdao  3.2  -6.6

同样,如果被赋值的列并不存在,则会生成一个新的列,我们增加一列,判断条件是city是否为沿海城市‘coastal city’:

>>>frame2['coastal city'] = frame2.city == 'qingdao'
>>>frame2
       year     city  pop  debt  coastal city
one    2018    Jinan  1.5   NaN         False
two    2019    jinan  1.7   NaN         False
three  2020    jinan  3.6  -1.2         False
four   2018  qingdao  2.4   NaN          True
five   2019  qingdao  2.0  -1.5          True
six    2020  qingdao  3.2  -6.6          True

DataFrame中,使用del关键字可以像在字典中那样对其的列进行删除:

>>>del frame2['coastal city']
>>>frame2.columns
Index(['year', 'city', 'pop', 'debt'], dtype='object')

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

>>>pop = {'jinan':{2018:2.2, 2019:2.3},'qingdao':{2018:3.5, 2019:3.6, 2020:3.7}}
>>>frame3 = pd.DataFrame(pop)
>>>frame3
      jinan  qingdao
2018    2.2      3.5
2019    2.3      3.6
2020    NaN      3.7

在这里可以使用类似NumPy的语法对DataFrame进行转置操作(行列互换):

>>>frame3.T
         2018  2019  2020
jinan     2.2   2.3   NaN
qingdao   3.5   3.6   3.7

嵌套列表传入DataFrame时,内部的字典的键会被联合、排序成为行的索引,如果这时显式的指明索引的话,内部字典的键则不会被排序,如果传入的index对象不在内部字典的键中,则会新建一个缺失值的行。

>>>pd.DataFrame(pop, index=[2021, 2020, 2019, 2018])
      jinan  qingdao
2021    NaN      NaN
2020    NaN      3.7
2019    2.3      3.6
2018    2.2      3.5

与嵌套字典相同,包含Series的字典也可以用来构造DataFrame

pdata = {'jinan':frame3['jinan'][:-1], 'qingdao':frame3['qingdao'][:2]}
pd.DataFrame(pdata)
      jinan  qingdao
2018    2.2      3.5
2019    2.3      3.6

DataFrame的索引和列也拥有name属性,当被赋值时,这些name属性也会被显示:

>>>frame3.index.name = 'year'
>>>frame3.columns.name = 'city'
#更像一个表格的样子了!
>>>frame3
city  jinan  qingdao
year                
2018    2.2      3.5
2019    2.3      3.6
2020    NaN      3.7

最后,和Series类似,DataFramevalues属性会将包含早在DataFrame中数据以二维数组的形式返回,如果DataFrame的列是不同的dtype,那valuesdtype会自动选择适合所有列的类型:

>>>frame2.values
array([[2018, 'Jinan', '1.5', nan],
       [2019, 'jinan', '1.7', nan],
       [2020, 'jinan', '3.6', -1.2],
       [2018, 'qingdao', '2.4', nan],
       [2019, 'qingdao', '2.0', -1.5],
       [2020, 'qingdao', '3.2', -6.6]], dtype=object)

DataFrame构造函数的有效输入

类型说明
2D nadarry数据的矩阵,行和列的标签是可选参数
数组、列表和元组构成的字典每个序列成为DataFrame的一列,要求所有序列必须长度相等
NumPy结构化/记录化数组与构成数组的字典一致
Series构成的字典每个值成为一列,每个Series的索引联合起来形成结果行的索引,也可以显示的传递索引
字典构成的字典每一个内部字典成为一列,键联合起来形成结果的行索引
字典或者Series构成的列表列表中的一个元素形成DataFrame的一行,字典的键或者Series索引联合起来形成DataFrame的列标签
列表或者元组构成的列表与2D nadarry情况一致
其他DataFrame如果不显式的传递索引,则会使用原DataFrame的索引
NumPy MaskedArry与2D nadarry情况类似,但隐蔽值会在结果DataFrame中成为NA/缺失值
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值