一.pandas的数据结构介绍
1.Series
Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由 一组数据即可产生最简单的Series:import pandas as pdobj = pd.Series([4, 7, -5, 3])print(obj)# 0 4# 1 7# 2 -5# 3 3# dtype: int64
2.DataFrame
它是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值,字符串,布尔值等).它既有行索引又有列索引,它可以被看作由Series组成的字典(共用同一个索引).3.索引对象
pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等).构建Series或DataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个Index,Index对象是不可修改的,因此用户不能对其进行修改二.基本功能
1.重新索引
一个重要方法是reindex,其作用是创建一个新对象,它的数据符合新的索引:import pandas as pd# 用该Series的reindex将会根据新索引进行重排。如果某个索引值在原始索引中当不存在,那么就会引入缺失值NaN:obj = pd.Series(data=[4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])print(obj) # 运行情况如下:# d 4.5# b 7.2# a -5.3# c 3.6# dtype: float64obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])print(obj2) # 运行情况如下:# a -5.3# b 7.2# c 3.6# d 4.5# e NaN# dtype: float64
对于时间序列这样的有序数据,重新索引时可能需要做一些插值处理。method选项即可达到此目的,例如,使用ffill可以实现前向值填充:
obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])obj4 = obj3.reindex(index=range(6))print(obj4) # 运行结果如下:# 0 blue# 1 NaN# 2 purple# 3 NaN# 4 yellow# 5 NaN# dtype: objectprint('--------------')obj5 = obj3.reindex(index=range(6), method='ffill')print(obj5) # 运行结果如下:# 0 blue# 1 blue# 2 purple# 3 purple# 4 yellow# 5 yellow# dtype: object
借助DataFrame,reindex可以修改(行)索引和列。只传递一个序列时,会
重新索引结果的行:
import numpy as npimport pandas as pdframe = pd.DataFrame(data=np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'], columns=['Ohio', 'Texas', 'California'])print(frame) # 运行结果如下:# Ohio Texas California# a 0 1 2# c 3 4 5# d 6 7 8frame2 = frame.reindex(['a', 'b', 'c', 'd'])print(frame2) # 运行结果如下:# Ohio Texas California# a 0.0 1.0 2.0# b NaN NaN NaN# c 3.0 4.0 5.0# d 6.0 7.0 8.0# 列可以用columns关键字重新索引:frame3 = frame.reindex(columns=['Texas', 'Utah', 'California'])print(frame3) # 运行结果如下:# Texas Utah California# a 1 NaN 2# c 4 NaN 5# d 7 NaN 8
如下列出了reindex函数的各参数及说明:
2.丢弃指定轴上的项
丢弃某条轴上的一个或多个项很简单,只要有一个索引数组或列表即可。由于需要执行一些数据整理和集合逻辑,所以drop方法返回的是一个在指定轴上删除了指定值的新对象:import numpy as npimport pandas as pdobj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])print(obj) # 运行结果如下:# a 0.0# b 1.0# c 2.0# d 3.0# e 4.0# dtype: float64new_obj = obj.drop('c')print(new_obj) # 运行结果如下:# a 0.0# b 1.0# d 3.0# e 4.0# dtype: float64# 对于DataFrame,可以删除任意轴上的索引值data = pd.DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four'])print(data) # 运行结果如下:# one two three four# Ohio 0 1 2 3# Colorado 4 5 6 7# Utah 8 9 10 11# New York 12 13 14 15data1 = data.drop(index=['Ohio'])print(data1) # 运行结果如下:# one two three four# Colorado 4 5 6 7# Utah 8 9 10 11# New York 12 13 14 15data2 = data.drop(columns=['one'])print(data2) # 运行结果如下:# two three four# Ohio 1 2 3# Colorado 5 6 7# Utah 9 10 11# New York 13 14 15# 许多函数,如drop,会修改Series或DataFrame的大小或形状,可以就地修改对象,不会返回新的对象:data.drop(index=['Colorado'], inplace=True)print(data) # 运行结果如下:# one two three four# Ohio 0 1 2 3# Utah 8 9 10 11# New York 12 13 14 15
3.索引,选取和过滤
Series索引(obj[...])的工作方式类似于NumPy数组的索引,只不过Series的索引值不只是整数:import numpy as npimport pandas as pdobj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])print(obj) # 运行结果如下:# a 0.0# b 1.0# c 2.0# d 3.0# dtype: float64# 如下两种方式是异曲同工的,运行结果都是 0.0print(obj['a'])print(obj[0])# 一次获取多个索引,左闭右开的,如下三种方式是异曲同工的.print(obj[2:4])# c 2.0# d 3.0# dtype: float64print(obj[['c', 'd']])# c 2.0# d 3.0# dtype: float64# 取第1,3个索引的值print(obj[[1, 3]])# b 1.0# d 3.0# dtype: float64# 取出obj中值小于6的所有数据print(obj[obj < 6])# a 0.0# b 1.0# c 2.0# d 3.0# dtype: float64print(obj['a':'c'])# a 0.0# b 1.0# c 2.0# dtype: float64# 用切片可以对Series的相应部分进行设置:obj['a':'c'] = 100print(obj)# a 100.0# b 100.0# c 100.0# d 3.0# dtype: float64
用一个值或序列对DataFrame进行索引其实就是获取一个或多个列:
import numpy as npimport pandas as pddata = pd.DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four'] )print(data)# one two three four# Ohio 0 1 2 3# Colorado 4 5 6 7# Utah 8 9 10 11# New York 12 13 14 15# 取 'two'列print(data['two'])# Ohio 1# Colorado 5# Utah 9# New York 13# Name: two, dtype: int64# 取 'one','two'列print(data[['one', 'two']])# one two# Ohio 0 1# Colorado 4 5# Utah 8 9# New York 12 13
这种索引方式有几个特殊的情况。首先通过切片或布尔型数组选取数据:
# 取出索引为[0,2)的所有数据print(data[:2])# one two three four# Ohio 0 1 2 3# Colorado 4 5 6 7# 取出 'three'列中值大于5的所有数据print(data[data['three'] > 5])# one two three four# Colorado 4 5 6 7# Utah 8 9 10 11# New York 12 13 14 15# 另一种用法是通过布尔型DataFrame(比如下面这个由标量比较运算得出的)进行索引:data[data < 5] = 0print(data)# one two three four# Ohio 0 0 0 0# Colorado 0 5 6 7# Utah 8 9 10 11# New York 12 13 14 15
用loc和iloc进行选取,对于DataFrame的行的标签索引,我们引入了特殊的标签运算符loc和iloc。它们可以让你用类似NumPy的标记,使用轴标签(loc)或整数索引(iloc),从DataFrame选择行和列的子集。
import numpy as npimport pandas as pddata = pd.DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four'] )print(data)# one two three four# Ohio 0 1 2 3# Colorado 4 5 6 7# Utah 8 9 10 11# New York 12 13 14 15# 我们通过标签选择一行和多列:print(data.loc['Colorado', ['one', 'two']])# one 4# two 5# Name: Colorado, dtype: int64# 然后用iloc和整数进行选取:print(data.iloc[2, [0, 1, 2]])# one 8# two 9# three 10# Name: Utah, dtype: int64# 获取一整行数据print(data.iloc[2])# one 8# two 9# three 10# four 11# Name: Utah, dtype: int64#有行有列print(data.iloc[[1, 2], [1, 3]])# two four# Colorado 5 7# Utah 9 11
这两个索引函数也适用于一个标签或多个标签的切片:
print(data.loc[:'Utah', 'two'])# Ohio 1# Colorado 5# Utah 9# Name: two, dtype: int64print(data.iloc[:, :3][data['three'] > 5])# one two three# Colorado 4 5 6# Utah 8 9 10# New York 12 13 14
在pandas中有多个方法可以选取和重新组合数据。对于DataFrame,做了如下的总结:
4.算术运算和数据对齐
pandas最重要的一个功能是,它可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。对于有数据库经验的用户,这就像在索引标签上进行自动外连接。import numpy as npimport pandas as pds1 = pd.Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1], index=['a', 'c', 'e', 'f', 'g'])print(s1)# a 7.3# c -2.5# d 3.4# e 1.5# dtype: float64print(s2)# a -2.1# c 3.6# e -1.5# f 4.0# g 3.1# dtype: float64# Series 进行加和操作,自动的数据对齐操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播。s3 = s1 + s2print(s3)# a 5.2# c 1.1# d NaN# e 0.0# f NaN# g NaN# dtype: float64# 对于DataFrame,对齐操作会同时发生在行和列上:df1 = pd.DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'), index=['Ohio', 'Texas', 'Colorado'])df2 = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])# 把它们相加后将会返回一个新的DataFrame,其索引和列为原来那两个DataFrame的并集,因为'c'和'e'列均不在两个DataFrame对象中,在结果中以缺省值呈现。行也是同样。print(df1)# b c d# Ohio 0.0 1.0 2.0# Texas 3.0 4.0 5.0# Colorado 6.0 7.0 8.0print(df2)# b d e# Utah 0.0 1.0 2.0# Ohio 3.0 4.0 5.0# Texas 6.0 7.0 8.0# Oregon 9.0 10.0 11.0df3 = df1 + df2print(df3)# b c d e# Colorado NaN NaN NaN NaN# Ohio 3.0 NaN 6.0 NaN# Oregon NaN NaN NaN NaN# Texas 9.0 NaN 12.0 NaN# Utah NaN NaN NaN NaN
5.在算术方法中填充值
在对不同索引的对象进行算术运算时,你可能希望当一个对象中某个轴标签在另一个对象中找不到时填充一个特殊值(比如0):import numpy as npimport pandas as pddf1 = pd.DataFrame(np.arange(12.).reshape((3, 4)), columns=list('abcd'))df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)), columns=list('abcde'))df2.loc[1, 'b'] = np.nanprint(df1)# a b c d# 0 0.0 1.0 2.0 3.0# 1 4.0 5.0 6.0 7.0# 2 8.0 9.0 10.0 11.0print(df2)# a b c d e# 0 0.0 1.0 2.0 3.0 4.0# 1 5.0 NaN 7.0 8.0 9.0# 2 10.0 11.0 12.0 13.0 14.0# 3 15.0 16.0 17.0 18.0 19.0print('--------')# 将它们相加时,没有重叠的位置就会产生NA值df3 = df1 + df2print(df3)# a b c d e# 0 0.0 2.0 4.0 6.0 NaN# 1 9.0 NaN 13.0 15.0 NaN# 2 18.0 20.0 22.0 24.0 NaN# 3 NaN NaN NaN NaN NaN# 使用df1的add方法,传入df2以及一个fill_value参数:df4 = df1.add(df2, fill_value=0)print(df4)# a b c d e# 0 0.0 2.0 4.0 6.0 4.0# 1 9.0 5.0 13.0 15.0 9.0# 2 18.0 20.0 22.0 24.0 14.0# 3 15.0 16.0 17.0 18.0 19.0# 如下表格列出了Series和DataFrame的算术方法。它们每个都有一个副本,以字母r开头,它会翻转参数。因此这两个语句是等价的:tmp=1/df1print(tmp)# a b c d# 0 inf 1.000000 0.500000 0.333333# 1 0.250 0.200000 0.166667 0.142857# 2 0.125 0.111111 0.100000 0.090909tmp2=df1.rdiv(1)print(tmp2)# a b c d# 0 inf 1.000000 0.500000 0.333333# 1 0.250 0.200000 0.166667 0.142857# 2 0.125 0.111111 0.100000 0.090909
6.DataFrame和Series之间的运算
跟不同维度的NumPy数组一样,DataFrame和Series之间算术运算也是有明确规定的import numpy as npimport pandas as pdarr = np.arange(12.).reshape((3, 4))print(arr)print(arr[0])# [0. 1. 2. 3.]# 当我们从arr减去arr[0],每一行都会执行这个操作。这就叫做广播(broadcasting)substra = arr - arr[0]print(substra)# [0. 1. 2. 3.]# [[0. 0. 0. 0.]# [4. 4. 4. 4.]# [8. 8. 8. 8.]]frame = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])print(frame)# b d e# Utah 0.0 1.0 2.0# Ohio 3.0 4.0 5.0# Texas 6.0 7.0 8.0# Oregon 9.0 10.0 11.0# 取第0行数据series = frame.iloc[0]print(series)# b 0.0# d 1.0# e 2.0# Name: Utah, dtype: float64# 默认情况下,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着行一直向下广播:tmp = frame - seriesprint(tmp)# b d e# Utah 0.0 0.0 0.0# Ohio 3.0 3.0 3.0# Texas 6.0 6.0 6.0# Oregon 9.0 9.0 9.0# 如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集:series2 = pd.Series(range(3), index=['b', 'e', 'f'])tmp2 = frame + series2print(tmp2)# b d e f# Utah 0.0 NaN 3.0 NaN# Ohio 3.0 NaN 6.0 NaN# Texas 6.0 NaN 9.0 NaN# Oregon 9.0 NaN 12.0 NaN# 如果你希望匹配行且在列上广播,则必须使用算术运算方法,frame的每列都减去series3series3 = frame['d']tmp3 = frame.sub(series3, axis='index')print(frame)# b d e# Utah 0.0 1.0 2.0# Ohio 3.0 4.0 5.0# Texas 6.0 7.0 8.0# Oregon 9.0 10.0 11.0print(series3)# Utah 1.0# Ohio 4.0# Texas 7.0# Oregon 10.0# Name: d, dtype: float64print(tmp3)# b d e# Utah -1.0 0.0 1.0# Ohio -1.0 0.0 1.0# Texas -1.0 0.0 1.0# Oregon -1.0 0.0 1.0
欢迎大家点个在看,分享至朋友圈 记录技术记录我