Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。
输出时:索引在左边,值在右边,如果没有指定索引,则自动创建0-N-1的整数型索引,可以通过series的value和index获取数组的表示形式和索引对象
添加索引:在index参数中添加与数组同长度的数组,对各个数据点进行标记
使用索引进行选取series的单个值或一组值
obj2['a'] # 单个值 obj2[['a','b','c']] # 一组值
使用NumPy函数或类似NumPy的运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引值的链接
obj2[obj2 > 0] obj2 * 2 np.exp(obj2)
可以将series看成定长的有序字典,可以将其看成索引值到数据值的映射,可以用在许多原本需要字典参数的函数
# 使用字典创建series sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000} obj3 = pd.Series(sdata)
如果只传入一个字典,则结果Series中的索引就是原字典的键(有序排列)。你可以传入排好序的字典的键以改变顺序:
states = ['California', 'Ohio', 'Oregon', 'Texas'] obj4 = pd.Series(sdata, index=states)
如果传入的index在是sdata中没有找到对应的值,则其结果的值就会为NAN(表示缺失或NA值),如果sdata中有值,而索引未传入,则直接从结果中抹除
pandas的isnull
和notnull
函数可用于检测缺失数据
pd.isnull(obj4) pd.notnull(obj4)
series中最重要的一个功能:能根据运算的索引标签自动对齐数字,类似于数据库的join方法
series对象本身与其索引都有一个name属性
series的索引可以通过赋值的方式就地修改,必须修改全部的索引,不能部分修改
obj = pd.Series([4,7,-5,3],index=range(4)) # 0 4 # 1 7 # 2 -5 # 3 3 # dtype: int64 obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan'] # 正确的 # Bob 4 # Steve 7 # Jeff -5 # Ryan 3 # dtype: int64 obj.index[0] = 1 # 错误的
DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。
建DataFrame:
head方法:
# head方法会选取前5行数据 frame.head()
建立DataFrame时,如果传入列序列,在DataFrame的列就会按照指定顺序进行排列
pd.DataFrame(data, columns=['year', 'state', 'pop'])
如果传入的列在数据中找不到,则会在结果中产生缺失值
通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series
列也可以通过复制的方式进行修改
frame2['debt'] = 16.5
当使用列表或数组进行赋值给某列时,其长度必须与DataFrame的长度相匹配,如果赋值的是Series,则会精确匹配DataFrame的索引。如果为不存在的列赋值则会创建出一个新列,注:不能用frame.eastern创建新的列
del方法可以用来删除这列
使用类似NumPy数组的方法,对DataFrame进行转置frame.T
如果设置的DataFrame的index和columns的name属性,则这些信息会被显示出来
与series一样,value属性会以二维ndarry的形式返回DataFrame中的数据
如果DataFrame各列的数据类型不同,则值数组的的type会选用能兼容所有列的数据类型
pandas的索引对象负者管理轴标签和其他元数据,构建Series和DataFrame时,所用到的任何数组或其他序列的标签都会被换成一个Index
Index对象是不可变的,因此用户不能对其进行修改
不可变可以使Index对象在多个数据结构之间安全共享
除了类似于数组,index也类似于一个固定大小的集合,但与Python不同的是,pandas的index可以包含重复的标签,选择重复的标签,会显示所有结果
reindex()
根据新索引进行重排,如果某个索引值当前不存在,就引入缺失值
method='ffill'
实现前项值填充
借助DataFrame,reindex可以修改(行)索引和列。只传递一个序列时,会重新索引结果的行,重新索引列时,用columns关键字重新索引
丢弃某条轴上的一个或多个项很简单,只要有一个索引数组或列表即可。由于需要执行一些数据整理和集合逻辑,所以drop方法返回的是一个在指定轴上删除了指定值的新对象
对于DataFrame,可以删除任意轴上的索引值,不指定轴,则默认删除行标签(axis=0),要删除列的值,则传递axis=1或axis=columns
可以就地修改对象,传入inplace=True
小心使用inplace,它会销毁所有被删除的数据
Series索引的工作方式类似于Numpy数组的索引,只不过Series索引值不只是整数
obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd']) obj['b'] obj[1] obj[2:4] obj[['b', 'a', 'd']] obj[[1, 3]] obj[obj < 2]
切片运算与Python切片不同,使用标签进行切片其末端是包含的obj['b':'c]
是包含c的,使用索引切片是不包含末端的obj[0:3]
,使用用切片可以对Series的相应部分进行设置
用一个值或序列对DataFrame进行索引其实就是获取一个或多个列
索引方式有几个特殊情况,首先通过切片或布尔型数组选取数据
data[:2] data[data['three'] > 5]
引入特殊的标签运算符loc和iloc,使用轴标签(loc)和整数索引(iloc)从DataFrame选择行和列的子集
data.loc['Colorado', ['two', 'three']]
data.iloc[2, [3, 0, 1]]
对于整数索引与Python内置的列表和元组的索引语法不同
ser = pd.Series(np.arange(3.)) ser ser[-1] # error
如果是非整数索引
ser2 = pd.Series(np.arange(3.), index=['a', 'b', 'c']) ser2[-1] # 2.0
如果轴索引含有整数,数据选取总会使用标签。为了更准确,请使用loc(标签)或iloc(整数)
pandas最重要的一个功能是,它可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。对于有数据库经验的用户,这就像在索引标签上进行自动外连接
自动的数据对齐操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播。对于DataFrame,对齐操作会同时发生在行和列上,其索引和列是原来两个DataFrame的并集
使用算术运算,在没有重叠的位置会产生NA值,而使用填充值,避免NA值
In [165]: df1 = pd.DataFrame(np.arange(12.).reshape((3, 4)), .....: columns=list('abcd')) In [166]: df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)), .....: columns=list('abcde')) In [167]: df2.loc[1, 'b'] = np.nan In [168]: df1 Out[168]: 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.0 In [169]: df2 Out[169]: 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.0 # 使用算术运算会出现NA值 In [170]: df1 + df2 Out[170]: 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 # 进行填充,避免出现NA值 In [171]: df1.add(df2, fill_value=0) Out[171]: 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开头,他会翻转参数,
DataFrame和Series之间会进行广播运算
默认情况下,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着行一直向下广播
如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集
在列上广播,则必须使用算术运算方法
frame.sub(series3, axis='index')
NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象
frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),index=['Utah', 'Ohio', 'Texas', 'Oregon']) np.abs(frame)
将函数应用到由各列或行所形成的一维数组上
f = lambda x: x.max() - x.min() frame.apply(f)# 在每列中执行一次, frame.apply(f,axis='columns')# 在每行中执行一次
传递到apply的函数不是必须返回一个标量,还可以返回由多个值组成的Series
将函数应用到元素
applymap()
将函数应用到元素上
format = lambda x: '%.2f' % x frame.applymap(format)
使用sort_index方法,返回一个已排序的新对象
对于Series,使用sort_index可以根据index排序
对于DataFrame,使用sort_index可以根据传入参数(axis)来对任意轴的索引进行排序
数据默认是升序,但也可以是降序排列ascending=False
若要按值进行排序,sort_values
,
任何缺失值都会默认放到Series末尾,当排序DataFrame时,根据一个或多个列中的值进行排序,那就将一个或多个值的名字传递给sort_values中的by选项,多个值时,先对前一个排序,若其中有相等的,再根据第二个值排序
rank方法:默认情况下,rank是通过“为各组分配一个平均排名”的方式破坏平级关系的
默认使用average
,即有相同排名时,取其排名的平均值
min
对于相等的值,取较小的排名
max
对于相等的值,取较大的排名
first
对于相等的值,取最先出现的排名
dense
类似于 ”min“,但排名不会出现大于 1 的空隙
索引的is_unique属性,用来判断它的值是否唯一
如果索引对应多个值,则会返回一个Series,而对应单个的值,则返回一个标量值,
Series的corr方法用于计算两个Series中重叠的、非NA的、按索引对齐的值的相关系数。与此类似,cov用于计算协方差
DataFrame的corr和cov方法将以DataFrame的形式分别返回完整的相关系数或协方差矩阵
DataFrame的corrwith方法,计算其列或行跟另一个Series或DataFrame之间的相关系数。传入一个Series将会返回一个相关系数值Series(针对各列进行计算)
unique
得到Series中唯一值数组
value_counts
用于计算一个Series中各值出现的频率,可用于任何数组或序列
isin
判断矢量化集合的成员资格,可用于过滤Series中或DataFrame列中数据的子
index.get_indexer
与isin类似的是Index.get_indexer方法,它可以给你一个索引数组,从可能包含重复值的数组到另一个不同值的数组
函数选项的大致分类
索引:将一个或多个列当做返回的DataFrame处理,以及是否从文件、用户获取列名。
类型推断和数据转换:包括用户定义值的转换、和自定义的缺失值标记列表等。
日期解析:包括组合功能,比如将分散在多个列中的日期时间信息组合成结果中的单个列。
迭代:支持对大文件进行逐块迭代。
不规整数据问题:跳过一些行、页脚、注释或其他一些不重要的东西(比如由成千上万个逗号隔开的数值数据)。
sep='分隔符'
指定分隔符
header=None
让pandas为其分配默认的列名
可以自己定义列名name=['a', 'b', 'c', 'd', 'message']
如果希望message列作为索引,可以明确表示要将该列放到索引4的位置上,也可以通过index_col参数指定"message"
做一个层次化索引,传入由列编号,或列名组成的列表即可
parsed = pd.read_csv('examples/csv_mindex.csv',index_col=['key1', 'key2'])
传入正则表达式作为分隔符
result = pd.read_table('examples/ex3.txt', sep='\s+')
跳过文件的某些行
pd.read_csv('examples/ex4.csv', skiprows=[0, 2, 3])
跳过文件的第一、三、四行
对某些值进行标记,将其标记为NA值
看大文件之前,将pandas显示的更急一些
显示10行数据
pd.options.display.max_rows = 10
只读取几行数据
pd.read_csv('examples/ex6.csv', nrows=5)
逐块读取文件【通过指定chunksize】
chunker = pd.read_csv('ch06/ex6.csv', chunksize=1000)
返回TextParser对象,可以进行迭代
tot = pd.Series([]) for piece in chunker: tot = tot.add(piece['key'].value_counts(), fill_value=0)
利用DataFrame的to_csv
方法将数据写到一个以逗号分隔的文件中
sep='字符串'
可以指定其他分隔符
缺失值会被标记为空字符串,也可以标记为其他的标记值na_rep="NULL"
使用na_rep将缺失值标记为NULL
如果没有设置其他选项,会写出行和列的标签,也可以进行禁用index=False,header=False
也可以只写出部分列data.to_csv(sys.stdout, index=False, columns=['a', 'b', 'c'])
不写入索引,并且只写入列为a,b,c,并且按写入的顺序排列
Series也有to_csv
方法
已经成为通过HTTP请求在Web浏览器和其他应用程序之间发送数据的标准格式之一。它是一种比表格型文本格式(如CSV)灵活得多的数据格式。
json.loads(obj)
实现将JSON字符串转换为Python形式
json.dumps(obj)
实现将Python对象转化为JSON格式
pandas.read_json
可以自动将特别的JSON数据集转化为Series或DataFrame
to_json
方法:将数据从pandas输出到JSON
实现数据的高效二进制格式存储最简单的办法之一是使用Python内置的pickle序列化
pandas对象都有一个用于将数据以pickle格式保存到磁盘上的to_pickle方法
frame.to_pickle('examples/frame_pickle')
可以通过pickle直接读取被pickle化的数据,或是使用更为方便的pandas.read_pickle
pd.read_pickle('examples/frame_pickle')
pandas的ExcelFile类或pandas.read_excel函数支持读取存储在Excel 2003(或更高版本)中的表格型数据。这两个工具分别使用扩展包xlrd和openpyxl读取XLS和XLSX文件。你可以用pip或conda安装它们
要使用ExcelFile,通过传递xls或xlsx路径创建一个实例
xlsx = pd.ExcelFile('examples/ex1.xlsx')
使用read_excel
读取到DataFrame中
pd.read_excel(xlsx, 'Sheet1')
将pandas数据写入为Excel格式
首先创建一个ExcelWriter,然后使用pandas对象的to_excel
方法将数据写入其中
writer = pd.ExcelWriter('examples/ex2.xlsx') frame.to_excel(writer, 'Sheet1') writer.save()
也可以不使用ExcelWriter,而是直接传递文件的路径到to_excel
frame.to_excel('examples/ex2.xlsx')
对于series
可以通过pandas.isnull或布尔索引的手工方法
dropna
会更实用一些,并且返回一个含非空数据和索引值的Series
data.dropna() # 等价于 data[data.notnull()]
对于DataFrame
dropna()
默认丢弃任何含有缺失值的行
指定axis=1
丢弃任何含有缺失值的列
how='all'
只丢弃那些全为NA的行或列
thesh=2
保留至少2行,留下一部分观测数据
fillna()
方法通过一个常数调用fillna将缺失值替换为常数
通过调用fillna()
可以实现对不同的列填充不同的值
fillna
会返回新对象,但也可以对现有对象进行就地修改
对reindexing
有效的插值方法也可用于fillna()
df.fillna(method='ffill')
# 向前填充
df.fillna(method='ffill', limit=2)
向前填充,限制为2
DataFrame的duplicated()
返回一个布尔型Series,表示各行是否是重复的行(前面出现过的行)
data.duplicated()
drop_duplicates()
返回一个一个DataFrame,重复的数组会标为False
默认判断全部列,可以指定部分列进行重复项判断data.drop_duplicates(['k1'])
根据k1列过滤重复项
默认保存的是第一次出现的值组合,传入keep='last'
则保留最后一个
map()
函数
Series的str.lower()
将各个值转换为小写
data['animal'] = lowercased.map(meat_to_animal)
animal是新建的列,meat_to_animal是不同肉类到动物的映射
也可以传入函数
data['food'].map(lambda x: meat_to_animal[x.lower()])
利用replace
来产生一个新的Series(除非传入inplace=True)
data.replace(-999, np.nan)
将-999替换为NaN
如果需要一次性替换多个值,传入一个待替换组成的列表以及一个替换值
data.replace([-999, -1000], np.nan)
如果要每个值的替换值都不一样则传入一个替换列表
data.replace([-999, -1000], [np.nan,0])
也可以传入字典
data.replace({-999: np.nan, -1000: 0})
跟Series中的值一样,轴标签也可以通过函数或映射进行转换,从而得到一个新的不同标签的对象。轴还可以被就地修改,而无需新建一个数据结构
data.index.map()
将其传给data.index可以实现就地修改
data.index = data.index.map()
想要创建数据集的转换版(而不是修改原始数据)比较实用的是rename()
可以结合字典型对象实现对部分轴标签的更新
rename可以实现复制DataFrame并对其索引和列标签进行赋值。如果希望就地修改某个数据集,传入inplace=True即可
data.rename(index={'OHIO': 'INDIANA'}, inplace=True)
将OHIO修改为INDIANA
使用cut()
将数据划分
bins = [18, 25, 35, 60, 100] cats = pd.cut(ages, bins)
pandas返回的是一个特殊的Categorical对象
codes属性中的年龄数据的标签
cats.codes # array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8)
pd.value_counts(cats)是pandas.cut结果的面元计数。
跟“区间”的数学符号一样,圆括号表示开端,而方括号则表示闭端(包括)。哪边是闭端可以通过right=False进行修改
可 以通过传递一个列表或数组到labels,设置自己的面元名称
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior'] pd.cut(ages, bins, labels=group_names)
如果向cut传入的是面元的数量而不是确切的面元边界,则它会根据数据的最小值和最大值计算等长面元
data = np.random.rand(20) pd.cut(data, 4, precision=2) # [(0.34, 0.55], (0.34, 0.55], (0.76, 0.97], (0.76, 0.97], (0.34, 0.55], ..., (0.34, 0.55], (0.34, 0.55], (0.55, 0.76], (0.34, 0.55], (0.12, 0.34]] # Length: 20 # Categories (4, interval[float64]): [(0.12, 0.34] < (0.34, 0.55] < (0.55, 0.76] < (0.76, 0.97]]
precision=2限制小数只有两位
使用qcut()
根据样本分位数对数据进行面元划分
cut可能无法使各个面元中含有相同数量的数据点。而qcut由于使用的是样本分位数,因此可以得到大小基本相等的面元
选出全部含有“超过3或-3的值”的行,你可以在布尔型DataFrame中使用any方法
data[(np.abs(data) > 3).any(1)]
显示data中行有绝对值大于3的行
data[(np.abs(data) > 3).any(1)]
对值进行设置,将值限制在-3到3之间
利用numpy.random.permutation函数可以轻松实现对Series或DataFrame的列的排列工作(permuting,随机重排序)
然后就可以在基于iloc的索引操作或take函数中使用该数组了
df = pd.DataFrame(np.arange(5 * 4).reshape((5, 4))) # 创建数组 sampler = np.random.permutation(5) # 创建随机数组 df.take(sampler) #使用take使用随机数组进行排列
选取随机子集,在Series和DataFrame上使用sample()
要通过替换的方式产生样本(允许重复选择),可以传递replace=True到sample
choices = pd.Series([5, 7, -1, 6, 4]) draws = choices.sample(n=10, replace=True)
常用于统计建模或机器学习的转换方式是:将分类变量(categorical variable)转换为“哑变量”或“指标矩阵”
如果DataFrame的某一列中含有k个不同的值,则可以派生出一个k列矩阵或DataFrame(其值全为1和0)。pandas有一个get_dummies函数可以实现该功能(其实自己动手做一个也不难)。使用之前的一个DataFrame例子
df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],'data1': range(6)}) pd.get_dummies(df['key'])
DataFrame的列加上一个前缀,以便能够跟其他数据进行合并,get_dummies的prefix参数可以实现该功能