pandas


Pandas数据处理

DataFrame本质上是一种带行标签和列标签、支持相同类型数据和缺失值的多维数组。


1. Series对象

Pandas 的 Series对象是一个带索引数据构成的一维数组,可以用一个数组创建Series对象。

import pandas as pd
import numpy as np
data = pd.Series([1,2,3,4])
print(data)
"""
0    1
1    2
2    3
3    4
dtype: int64
"""

print(data.values)
#[1 2 3 4]

print(data.index)
"""
RangeIndex(start=0, stop=4, step=1)
"""

#获取数据
print(data[1])
print(data[1:3])
"""
2
1    2
2    3
dtype: int64
"""

Series是通用的Numpy数组
但两者间的本质差异是索引:Numpy数组通过隐式定义的整数索引获取数值,而Pandas的Series对象用一种显式定义的索引与数值关联。

显式索引

data = pd.Series([1,2,3,4],index=['a','b','c','d'])
print(data)
"""
a    1
b    2
c    3
d    4
dtype: int64
"""

#获取数值的方式
print(data['c'])
# 3

Series对象其实是一种将类型键映射到一组类型值得数据结构。

我们可以直接用python字典创建一个Series对象:

dict_demo = {
    'a':1,
    'b':2,
    'c':3,
    'd':4
}

ser_demo = pd.Series(dict_demo)
print(ser_demo)
"""
a    1
b    2
c    3
d    4
dtype: int64
"""

data可以是一个字典,默认是排序的字典键,但是可以通过显示指定索引筛选需要的结果:

ser_demo = pd.Series({2:'a',1:'b',3:'c'},index=[3,2])
print(ser_demo)
"""
3    c
2    a
dtype: object
"""

2. DataFrame对象

如果将Series类比为带灵活索引的一维数组,那么DataFrame就可以看作是一种既有灵活的行索引,又有灵活列名的二维数组。就像你可以把二维数组看成是有序排列的一维数组一样,你也可以把DataFrame看成是有序排列的若干Series对象,这里的“排列”指的是它们拥有共同的索引。

area = {'a':2,'b':4,'c':6}
area_ser = pd.Series(area)

population = {'a':100,'b':200,'c':300}
population_ser = pd.Series(population)

df_demo = pd.DataFrame({'area':area_ser,'population':population_ser})
print(df_demo)
print(df_demo.index)#获取行标签
print(df_demo.columns)#获取列标签
"""
   area  population
a     2         100
b     4         200
c     6         300

Index(['a', 'b', 'c'], dtype='object')
Index(['area', 'population'], dtype='object')
"""

#获取数据
print(df_demo['area'])
"""
a    2
b    4
c    6
Name: area, dtype: int64
"""

注意:在Numpy的二维数组里,data[0]返回第一行,而在DataFrame中,data[‘col1’]返回第一列。

2.1 创建DataFrame对象

#1. 通过单个Series对象创建。DataFrame是一组Series对象的集合,可以用单个Series创建一个单列的DataFrame
population = {'a':100,'b':200,'c':300}
population_ser = pd.Series(population)

df_single_col = pd.DataFrame(population_ser,columns=['population'])
print(df_single_col)
"""
   population
a         100
b         200
c         300
"""

#2. 通过字典列表创建
data = [{'a':i,'b':2*i} for i in range(3)]
pd_by_dict = pd.DataFrame(data)
print(pd_by_dict)
"""
   a  b
0  0  0
1  1  2
2  2  4
"""

#3. 通过Series对象字典创建。如示例在前面

#4. 通过Numpy二维数组创建。
df_by_np = pd.DataFrame(np.random.random((3,2)),index=[1,2,3],columns=[1,3])
print(df_by_np)
"""
          1         3
1  0.388610  0.687721
2  0.797138  0.763878
3  0.047219  0.901602
"""

Pandas的Index是一个很有趣的数据结构,可以将它看作是一个不可变数组或有序集合。

ind = pd.Index([1,2,3,4])
print(ind)
print(ind[1])
print(ind[::2])
print(ind.size,ind.shape,ind.ndim,ind.dtype)
"""
Int64Index([1, 2, 3, 4], dtype='int64')
2
Int64Index([1, 3], dtype='int64')
4 (4,) 1 int64
"""
#index对象与Numpy数组之间的不同在于,Index对象的索引是不可变的,一旦确定,不可以对它进行赋值操作。

Index对象遵循Python标准库的集合(set)数据结构的许多习惯用法,包括并集、交集、差集等:

indA = pd.Index([1,2,3,4,5])
indB = pd.Index([3,4,5,6,7])
print(indA&indB)
print(indA.intersection(indB))
"""
Int64Index([3, 4, 5], dtype='int64')
Int64Index([3, 4, 5], dtype='int64')
"""

2.2 数据取值与选择

(1) series 数据操作

data = pd.Series([1,3,4,5],index=['a','b','c','d'])
print(data['a'])
print('a' in data)
print(data.keys())#索引值
print(list(data.items()))#[('a', 1), ('b', 3), ('c', 4), ('d', 5)]
data['e'] = 1#增加新的索引值扩展字典
data['a':'c'] #显式索引作为切片
data[0:2]#隐式整数索引作为切片
data[(data>0.3) & (data<0.8)]#掩码操作
data[['a','e']]#花哨的索引
#第一种索引器是loc属性,表示取值和切片都是显式的:
data = pd.Series([1,2,3,4],index=[1,2,3,4])
data.loc[1]#1
data.loc[1:3]
#第二种是iloc属性,表示取值和切片都是python形式的隐式索引:
data.iloc[1]#2
data.iloc[1:3]
#第三种混合索引,忽略

(2) DataFrame 数据操作

area = {'a':2,'b':4,'c':6}
area_ser = pd.Series(area)

population = {'a':100,'b':200,'c':300}
population_ser = pd.Series(population)

df_demo = pd.DataFrame({'area':area_ser,'population':population_ser})

print(df_demo['area'])
print(df_demo.area)#这种方法不通用
df_demo['list'] = 23#增加一列为list
print(df_demo.T)

print(df_demo.values[0])#获取一行数据
print(df_demo['list'])#获取一列数据
df_demo.iloc[:3,:2]#获取前3行,2列数据
df_demo.loc[:'b',:2]#显式获取
df_demo.ix[]#混合获取,忽略
df_demo.loc[df_demo.area>2,['population']]#掩码和花哨获取
#任何一种取值方式都可以用于调整数据。

df_demo['area':'population']#取多行数据,和一列要互相区别
df_demo[:3]#取多行数据
df_demo[df_demo.area>1]

2.3 数值运算方法

因为pandas是建立在numpy基础之上的,所以numpy的通用函数同样适用于pandas的Series和DataFrame对象。

rng = np.random.RandomState(43)
ser = pd.Series(rng.randint(0,10,4))
df = pd.DataFrame(rng.randint(0,10,(3,4)),columns=
                  ['A','B','C','D'])
print(ser)
print(df)
np.exp(ser)
np.sin(df*np.pi/4)

#索引对齐
A = pd.Series([2,4,6],index=[0,1,2])
B = pd.Series([1,2,3],index=[1,2,3])
A+B#会出现NaN,因为索引不对齐
A.add(B,fill_value=0)#用0填充缺失值
#DataFrame类似
df = pd.DataFrame(rng.randint(0,20,(2,2)),columns=list('AB'))
#计算df的均值需要用stack将二维压缩成一维
df_mean = df.stack().mean()
python运算符pandas方法
+add()
-sub()、subtract()
*mul()、multiply()
/truediv()、div()、divide()
//floordiv()
%mod()
**pow()

2.4 处理缺失值

缺失值主要有三种形式:null、NaN和NA
在数据表或DataFrame中有很多识别缺失值的方法。一般情况下可以分为两种:一种方法是通过一个覆盖全局的掩码表示缺失值,另一种方法是用一个标签值(sentinel value)表示缺失值。
Pandas选择用标签方法表示缺失值,包括两种Python原有的缺失值:浮点数据类型的NaN值,以及Python的None对象。
可以把NaN看作是一个数据类病毒–它会将与它接触过的数据同化,无论和NaN进行何种操作,最终结果都是NaN。

#在Series里使用的isnull()和notnull()同样使用于DataFrame
#筛选出缺失值
data = pd.Series([1,np.nan,'hello',None])
print(data.isnull())
print(data.notnull())

#剔除缺失值
print(data.dropna())

df = pd.DataFrame(np.random.randint(1,10,(3,3)))
df.iloc[0,1] = np.nan
df.iloc[2,0] = np.nan
print(df.dropna())#相当于df.dropna(axis=0)
print(df.dropna(axis=1))
#还可以通过参数how或thresh参数来满足,默认设置how='any',你可以设置how='all',这样只会剔除全部是缺失值的行货列
#thres参数设置行货列中非缺失值的最小数量

#填充缺失值
# print(df.fillna(0))#用0填充
# print(df.fillna(method='ffill'))#用缺失值前面的有效值来从前往后填充(forward-fill)
print(df.fillna(method='bfill',axis=1))#用缺失值后面的有效值从后往前填充(back-fill)

2.5 合并数据集:Concat与Append操作

pd.concat()函数和np.concatenate语法类似。可以简单地合并一维的Series或DataFrame。

pd.concat([x,y],ignore_index=True)#忽略索引,如果索引重复,可以用参数verify_integrity=True检查
#也可以通过参数join设置合并的方式。通过join_axes设置索引对象构成的列表
df1.append(ddf2)#相当于pd.concat([df1,df2])
#append()不直接更新原有对象的值,而是为合并后的数据创建一个新对象。

2.6 合并数据集:合并与连接

Pandas的基本特性之一就是高性能的内存式数据连接(join)与合并(merge)操作。

数据连接的类型

pd.merge()函数实现了三种数据连接的类型:一对一、多对一和多对多。

一对一连接

df1 = pd.DataFrame({'employee':['Bob','Jake','Lisa','Sue'],
                    'group':['Accounting','Engineering','Engineering','HR']})
df2 = pd.DataFrame({'employee':['Bob','Jake','Lisa','Sue'],
                    'hire_date': [2004, 2008, 2012, 2014]})

df3 = pd.merge(df1,df2)
print(df3)
"""
  employee        group  hire_date
0      Bob   Accounting       2004
1     Jake  Engineering       2008
2     Lisa  Engineering       2012
3      Sue           HR       2014
"""
#pd.merge()方法会发现两个DataFrame都有employee列,并会自动以这列作为键进行连接。

多对一连接

多对一连接是指,在需要连接的两个列中,有一列的值有重复,通过多对一连接获得的结果DataFrame将会保留重复值。

df1 = pd.DataFrame({'employee':['Bob','Jake','Lisa','Sue'],
                    'group':['Accounting','Engineering','Engineering','HR']})
df2 = pd.DataFrame({'employee':['Bob','Jake','Lisa','Sue'],
                    'hire_date': [2004, 2008, 2012, 2014]})

df3 = pd.merge(df1,df2)
# print(df3)
df4 = pd.DataFrame({'group':['Accounting','Engineering','HR'],
                    'supervisor':['Carly','Guido','Steve']})
df5 = pd.merge(df3,df4)
print(df5)
"""
  employee        group  hire_date supervisor
0      Bob   Accounting       2004      Carly
1     Jake  Engineering       2008      Guido
2     Lisa  Engineering       2012      Guido
3      Sue           HR       2014      Steve
"""

多对多连接

如果左右两个输入的共同列都包含重复值,那么合并的结果就是一种多对多连接。

df5 = pd.DataFrame({'group':['Accounting','Accounting','Engineering',
                             'Engineering','HR','HR'],
                    'skills':['math','spreadsheets','coding','linux',
                              'spreadsheets','organization']})
df6 = pd.merge(df1,df5)
print(df6)
"""
  employee        group        skills
0      Bob   Accounting          math
1      Bob   Accounting  spreadsheets
2     Jake  Engineering        coding
3     Jake  Engineering         linux
4     Lisa  Engineering        coding
5     Lisa  Engineering         linux
6      Sue           HR  spreadsheets
7      Sue           HR  organization
"""

设置数据合并的键

pd.merge()的默认行为:将两个输入的一个或多个共同列作为键进行合并。但是由于两个输入要合并的列通常都不是同名的,因此pd.merge()提供了一些参数处理这个问题

参数on的用法

最简单的方法就是直接将参数on设置为一个列名字符串或者一个包含多列名称的列表。on=’col_name’

left_on与right_on参数

有时需要合并两个列名不同的数据集。这时候就可以用left_on和right_on参数来指定列名:
left_on = ‘left_col_name’,right_on = ‘right_col_name’
这个结果中,两个对应的列名都存在,也就是多了一个列名,可以使用drop()函数将多余的列去除

df4 = pd.DataFrame({'employee':['Bob','Jake','Lisa','Sue'],
                    'group':['Accounting','Engineering','Engineering','HR']})
df5 = pd.DataFrame({'g':['Accounting','Accounting','Engineering',
                             'Engineering','HR','HR'],
                    'skills':['math','spreadsheets','coding','linux',
                              'spreadsheets','organization']})
df6 = pd.merge(df4,df5,left_on='group',right_on='g').drop('g',axis=1)
print(df6)

left_index和right_index参数

除了合并列之外,你可能还需要合并索引。
为了方便考虑,DataFrame实现了join()方法,它可以按照索引进行数据合并:
df1.join(df2)

设置数据连接的集合操作规则
默认情况下,pd.merge()结果中只会包含两个输入集合的交集,这种连接方式被称为内连接(inner join),我们可以用how参数设置连接方式,默认值是‘inner’。(其他值有:outer,left,right)

重复列名:suffixes参数

当2个有重复列名的数据集进行连接的时候,系统会自动生成新的列名,我们也可以通过参数suffixes=[‘col_1’,‘col_2’]进行设置

2.7 累计和分组

在对较大数据进行分析时,一项基本的工作就是有效的数据累计:计算累计(aggregation)指标,如sum()、mean()、median()、min()和max()。

Pandas的累计方法

指标描述
count()计数项
first(),last()第一项和最后一项
mean(),median()均值和中位数
min(),max()最小值和最大值
std(),var()标准差和方差
mad()均值绝对偏差
prod()所有项乘积
sum()所有项求和

2.7 GroupBy:分割、应用和组合

df.groupby(‘key’)

GroupBy对象

GroupBy对象是一种非常灵活的抽象类型。
(1) 累计。aggregate()可以支持更复杂的操作,比如字符串、函数或者函数列表。并且能一次性计算所有累计值。
df.groupby(‘key’).aggregate([‘min’,np.median,max])

3 处理时间序列

工具:datetime和dateutil

4 eval()与query()

pd.eval(‘df1+df2+df3’)
目前pd.eval(0还不支持函数调用、条件语句、循环以及更复杂的运算。
df.eval()方法还支持通过@符号使用python的局部变量。@只能在df.eval()中使用,不能再pandas.eval()中使用。

query()
支持@符号引用局部变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值