利用Python进行数据分析——Pandas

import numpy as np
import pandas as pd

pandas中的数据结构有两种:Series和DataFrame。

Series

生成Series

obj=pd.Series([1,2,3,4],index=['a','b','c','d'])
obj

a 1
b 2
c 3
d 4
dtype: int64

Series可看成是定长、有序的字典结构,并且可以直接将Python字典转为Series:

sdata={
    'Ohio':35000,
    'Texas':71000,
    'Oregon':16000,
    'Utah':5000
}

obj_1=pd.Series(sdata)
obj_1

Ohio 35000
Oregon 16000
Texas 71000
Utah 5000
dtype: int64

Series可以存在缺失值:

states=['Calofornia','Ohio','Oregon','Texas']
obj_2=pd.Series(sdata,index=states)
obj_2

Calofornia NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
dtype: float64

属性

Series的常用属性为index与name。

obj_1.index

Index([‘Ohio’, ‘Oregon’, ‘Texas’, ‘Utah’], dtype=’object’)

Series的index可以直接更改:

obj_1.index=['state_1', 'state_2', 'state_3', 'state_4']
obj_1

state_1 35000
state_2 16000
state_3 71000
state_4 5000
dtype: int64

一个Series可以有自己的名字:

obj_2.name='population'
obj_2.index.name='state'
obj_2

state
Calofornia NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
Name: population, dtype: float64

索引

index索引

obj.loc['a']

1

obj.loc[['a','c','d']]

a 1
c 3
d 4
dtype: int64

布尔索引

obj[obj>2]

c 3
d 4
dtype: int64

基本运算

obj+2

a 3
b 4
c 5
d 6
dtype: int64

np.exp(obj)

a 2.718282
b 7.389056
c 20.085537
d 54.598150
dtype: float64

DataFrame

生成DataFrame

生成自定义生成DataFrame常用的方法是将Python字典转化为生成DataFrame:

states=['Ohio','Ohio','Ohio','Nevada','Nevada','Nevada']
years=[2000,2001,2002,2001,2002,2003]
pop=[1.5,1.7,3.6,2.4,2.9,3.2]
index=['one','two','three','four','five','six']
data={
    'state':states,
    'year':years,
    'pop':pop
}

frame=pd.DataFrame(data,index=index,columns=['year','state','pop'])
frame

属性

DataFrame的常用属性有index与values。

frame.index

Index([‘one’, ‘two’, ‘three’, ‘four’, ‘five’, ‘six’], dtype=’object’)

frame.values

数据预览

frame.sample(3)        #按行随机采样

增删查改

因为DataFrame属于表格型数据结构,所以增删查改的操作非常重要。

查询数据的方式主要有两种方法:loc与iloc,分别是根据标签索引与根据数字序号索引。

frame.loc[:,['state']]        #单列

frame.loc[['two'],:]        #单行

frame.loc[['three'],['pop']]        #单个数值

frame.loc['four':'six',['state','pop']]        #多行多列,非连续.注意字符形式的切片是闭区间

frame.iloc[3:6,[1,2]]        #多行多列,非连续,注意数字形式的切片是开区间

frame[frame['pop']>3]        #布尔索引

frame['eastern']=(frame.loc[:,'state']=='Ohio')        #增加列
frame

frame_2=frame.reindex(['one','two','three','inter','four','five','six'])        #增加行
frame_2

frame_1=frame.drop(['year','eastern'],axis=1,inplace=False)        #删除列
frame_1

frame_2=frame.drop(['three','five'],axis=0,inplace=False)        #删除行
frame_2

frame.loc[['two'],['pop']]=2.5        #改数据
frame

DF与DF的运算

df1=pd.DataFrame(np.arange(9).reshape((3,3)),index=['Ohio','Texas','Colorado'],columns=list('bcd'))
df2=pd.DataFrame(np.arange(12).reshape((4,3)),index=['Utah','Ohio','Texas','Oregon'],columns=list('bde'))
print("df1:\n{}".format(df1))
print("df2:\n{}".format(df2))

df1+df2        #df之间的加法,得到的数据为两表的交集,而标签为两表的并集

DF与Series的运算

在numpy中,一个矩阵与一个向量做运算会有广播机制,类似的,DF与Series做运算时也有广播机制。

frame=pd.DataFrame(np.arange(6).reshape((2,3)),index=np.arange(2),columns=list('abc'))
series=frame.iloc[0]
frame

series

a 0
b 1
c 2
Name: 0, dtype: int32

frame-series

应用函数

可以使用apply()与applymap()方法将一个函数应用到df的行列或每一个数据上。

frame=pd.DataFrame(np.random.randn(3,3),index=['Utah','Ohio','Texas'],columns=list('abc'))
frame

f_1=lambda x:x.max()-x.min()        #计算取值范围
f_2=lambda x:'%.2f' %x        #取两位有效数字
frame.applymap(f_2)        #对每一个数据都应用f_2函数

frame.apply(f_1,axis=0)        #计算每一列的范围

a 2.172817
b 1.145203
c 1.677505
dtype: float64

frame.apply(f_1,axis=1)        #计算每一行的范围

Utah 1.811939
Ohio 1.136488
Texas 1.611686
dtype: float64

排序与排名

frame=pd.DataFrame(np.arange(9).reshape((3,3)),index=['two','one','three'],columns=list('bca'))
frame

按标签排序

frame.sort_index(axis=0)        #按行标签排序

frame.sort_index(axis=1)        #按列标签排序

按数值排序

frame.sort_values(by='c',ascending=False)        #指定对'c'列降序排列

排名

(待补充)

统计方法

values=np.array([
    [1.4,np.nan],
    [7.1,-4.5],
    [np.nan,np.nan],
    [0.75,-1.3]
])

frame=pd.DataFrame(values,index=(['a','b','c','d']),columns=['one','two'])
frame

frame.mean(axis=0)

one 3.083333
two -2.900000
dtype: float64

frame.sum(axis=1)

a 1.40
b 2.60
c NaN
d -0.55
dtype: float64

frame.describe()

frame.info()

相关系数与协方差

price = pd.read_pickle('examples/yahoo_price.pkl')
volume = pd.read_pickle('examples/yahoo_volume.pkl')
returns = price.pct_change()
returns.sample(3)

returns.corr()        #相关系数矩阵

returns.cov()        #协方差矩阵

独特值,值的计数

frame=pd.DataFrame({
    'C1':[1,3,4,3,4],
    'C2':[2,3,1,2,3],
    'C3':[1,5,2,4,4]
})
frame.loc[:,'C1'].unique()

array([1, 3, 4], dtype=int64)

frame.loc[:,'C3'].value_counts(sort=False)

1 1
2 1
4 2
5 1
Name: C3, dtype: int64

布尔筛选

mask=frame.loc[:,'C2'].isin([1,2])
mask

0 True
1 False
2 True
3 True
4 False
Name: C2, dtype: bool

DF数据计数

result=frame.apply(pd.value_counts).fillna(0)
result

pandas进阶

类别型数据

obj=pd.Series(['apple','orange','banana','apple']*2)
pd.value_counts(obj)

许多数据仓库都有特殊的方式来存放重复值已增加存储和计算的效率,在数据仓库中一个最佳的实用方法是使用fact table来存储可运算的数据,再使用dimension table来存储描述性信息。如上述Series用两个表来存储的话如下所示:

fact=pd.Series([0,1,2,0]*2)
dim=pd.Series(['apple','orange','banana'])
dim.take(fact)

上述例子中的独特值’apple’与’orange’被称为类别或字典,而整数值被称为类别码,这种表达(存储)方式被称为类别编码或字典编码形式。这种方式会大大降低以下两种场景的开销:
- 类别重命名
- 在不改变已有类别顺序的情况下增加一个类别

fruits=['apple','orange','banana','apple']*2
df=pd.DataFrame({
    'fruit':fruits,
    'basket_id':np.arange(len(fruits)),
    'count':np.random.randint(3,15,size=len(fruits)),
    'weight':np.random.uniform(0,4,size=len(fruits))},
    columns=['basket_id','fruit','count','weight']
)

df.loc[:,'fruit']=df.loc[:,'fruit'].astype('category')
df.loc[:,'fruit']

类别型数据列取cat属性后得到一个类别型实例,它有两个属性,categories和codes:

c=df.loc[:,'fruit'].cat
print('{}\n{}'.format(c.categories,c.codes))

直接由字符串列表生成类别型:

str_list=['foo','bar','baz','foo','bar']
categories=pd.Categorical(str_list)
categories

由类别与编码生成类别型:

category_list=['foo','bar','baz']
codes_list=[0,1,2,0,0,1]
categories=pd.Categorical.from_codes(codes_list,category_list,ordered=True)
categories

类别计算

之前用过的cut()与qcut()方法返回的就是类别型,有些pandas操作在使用类别型时会有更好的表现,如groupby():

samples=np.random.randn(100)
bins=pd.qcut(samples,4,labels=['Q1','Q2','Q3','Q4'])
bins

bins.codes[:5]

bins=pd.Series(bins,name='quartile')
stat_result=pd.Series(samples).groupby(bins).agg(['min','max','mean']).reset_index()
stat_result

对于那些重复值很多的数据集而言,将其转化到类别型是很有用的,包括性能提升与更小的存储开销,看下面例子:

N=10000000
strs=pd.Series(['a','b','c','d']*(N//4))        #字符串型
cats=strs.astype('category')        #类别型
print(strs.memory_usage(),cats.memory_usage())        #内存使用差异

类别型方法

对于Series:

s=pd.Series(['a','b','c','d'])
cats1=s.astype('category')
cats2=cats1.cat.set_categories(['a','b','c','d','e'])        #改变类别
cats1.value_counts()

cats2.value_counts()

cats2.cat.remove_unused_categories()

当使用统计分析或者机器学习工具时,常需要将类别型转换成哑变量,或者是独热码:

cats=pd.Series(['a','b','c','a'],dtype='category')
pd.get_dummies(cats)

GroupBy进阶

组转换与展开GroupBy

df=pd.DataFrame({
    'key':['a','b','c']*2,
    'val':np.arange(6)
})
df.groupby('key').mean()

假设需要对’a’,’b’,’c’组的值用各组的均值来替换,可以使用transform()方法,这被称为展开GroupBy:

df.groupby('key').transform('mean')

transform()方法提供了类似于apply()方法的功能,不过有更多的限制:
- 它的输出与输入同形状
- 不改变输入

再看一个例子,将组里的每一个元素标准化:

def normalize(x):
    return (x-x.mean())/x.std()
df.groupby('key').transform(normalize)

分组时间重采样

(待补充)

方法链接技术

(待补充)

猜你喜欢

转载自blog.csdn.net/qq_31823267/article/details/79902622