您的位置:首页 > 编程语言 > Python开发

利用python进行数据分析笔记

2016-02-24 22:24 921 查看

pandas基础

索引

Series和DataFrame都是有索引的,索引的好处是快速定位,在涉及到两个Series或DataFrame时可以根据索引自动对齐,比如日期自动对齐,这样可以省去很多事。

缺失值

pd.isnull(obj)
obj.isnull()


将字典转成数据框,并赋予列名,索引

DataFrame(data, columns=['col1','col2','col3'...],
index = ['i1','i2','i3'...])


查看列名

DataFrame.columns


查看索引

DataFrame.index


重建索引

obj.reindex(['a','b','c','d','e'...], fill_value=0]
#按给出的索引顺序重新排序,而不是替换索引。如果索引没有值,就用0填充

#就地修改索引
data.index=data.index.map(str.upper)


列顺序重排(也是重建索引)

DataFrame.reindex[columns=['col1','col2','col3'...])`

#也可以同时重建index和columns

DataFrame.reindex[index=['a','b','c'...],columns=['col1','col2','col3'...])


重建索引的快捷键

DataFrame.ix[['a','b','c'...],['col1','col2','col3'...]]


重命名轴索引

data.rename(index=str.title,columns=str.upper)

#修改某个索引和列名,可以通过传入字典
data.rename(index={’old_index':'new_index'},
columns={'old_col':'new_col'})


查看某一列

DataFrame['state'] 或 DataFrame.state


查看某一行

需要用到索引

DataFrame.ix['index_name']


添加或删除一列

DataFrame['new_col_name'] = 'char_or_number'
#删除行
DataFrame.drop(['index1','index2'...])
#删除列
DataFrame.drop(['col1','col2'...],axis=1)
#或
del DataFrame['col1']


DataFrame选择子集

类型说明
obj[val]选择一列或多列
obj.ix[val]选择一行或多行
obj.ix[:,val]选择一列或多列
obj.ix[val1,val2]同时选择行和列
reindx对行和列重新索引
icol,irow根据整数位置选取单列或单行
get_value,set_value根据行标签和列标签选择单个值
针对series

obj[['a','b','c'...]]
obj['b':'e']=5


针对dataframe

#选择多列
dataframe[['col1','col2'...]]

#选择多行
dataframe[m:n]

#条件筛选
dataframe[dataframe['col3'>5]]

#选择子集
dataframe.ix[0:3,0:5]


dataframe和series的运算

会根据 index 和 columns 自动对齐然后进行运算,很方便啊

方法说明
add加法
sub减法
div除法
mul乘法
#没有数据的地方用0填充空值
df1.add(df2,fill_value=0)

# dataframe 与 series 的运算
dataframe - series
规则是:
--------   --------  |
|      |   |      |  |
|      |   --------  |
|      |             |
|      |             v
--------
#指定轴方向
dataframe.sub(series,axis=0)
规则是:
--------   ---
|      |   | |   ----->
|      |   | |
|      |   | |
|      |   | |
--------   ---


apply函数

f=lambda x:x.max()-x.min()

#默认对每一列应用
dataframe.apply(f)

#如果需要对每一行分组应用
dataframe.apply(f,axis=1)


排序和排名

#默认根据index排序,axis = 1 则根据columns排序
dataframe.sort_index(axis=0, ascending=False)

# 根据值排序
dataframe.sort_index(by=['col1','col2'...])

#排名,给出的是rank值

series.rank(ascending=False)
#如果出现重复值,则取平均秩次

#在行或列上面的排名
dataframe.rank(axis=0)


描述性统计

方法说明
count计数
describe给出各列的常用统计量
min,max最大最小值
argmin,argmax最大最小值的索引位置(整数)
idxmin,idxmax最大最小值的索引值
quantile计算样本分位数
sum,mean对列求和,均值
mediam中位数
mad根据平均值计算平均绝对离差
var,std方差,标准差
skew偏度(三阶矩)
Kurt峰度(四阶矩)
cumsum累积和
Cummins,cummax累计组大致和累计最小值
cumprod累计积
diff一阶差分
pct_change计算百分数变化

唯一值,值计数,成员资格

obj.unique()
obj.value_count()
obj.isin(['b','c'])


处理缺失值

# 过滤缺失值

# 只要有缺失值就丢弃这一行
dataframe.dropna()
#要求全部为缺失才丢弃这一行
dataframe.dropna(how='all')
# 根据列来判断
dataframe.dropna(how='all',axis=1)

# 填充缺失值

#1.用0填充
df.fillna(0)

#2.不同的列用不同的值填充
df.fillna({1:0.5, 3:-1})

#3.用均值填充
df.fillna(df.mean())

# 此时axis参数同前面,


将列转成行索引

df.set_index(['col1','col2'...])


数据清洗,重塑

合并数据集

# 取 df1,df2 都有的部分,丢弃没有的
# 默认是inner的连接方式
pd.merge(df1,df2, how='inner')

#如果df1,df2的连接字段名不同,则需要特别指定
pd.merge(df1,df2,left_on='l_key',right_on='r_key')

#其他的连接方式有 left,right, outer等。

# 如果dataframe是多重索引,根据多个键进行合并
pd.merge(left, right, on=['key1','key2'],how = 'outer')

#合并后如果有重复的列名,需要添加后缀
pd.merge(left, right, on='key1', suffixes=('_left','_right'))


索引上的合并

#针对dataframe中的连接键不是列名,而是索引名的情况。
pd.merge(left, right, left_on = 'col_key', right_index=True)
#即左边的key是列名,右边的key是index。

#多重索引
pd.merge(left, right, left_on=['key1','key2'], right_index=True)


dataframe的join方法

#实现按索引合并。
#其实这个join方法和数据库的join函数是以一样的理解
left.join(right, how='outer')

#一次合并多个数据框
left.join([right1,right2],how='outer')


轴向连接(更常用)

连接:concatenation

绑定:binding

堆叠:stacking

列上的连接

np.concatenation([df1,df2],axis=1)  #np包
pd.concat([df1,df2], axis=1) #pd包

#和R语言中的 cbind 是一样的

#如果axis=0,则和 rbind 是一样的
#索引对齐,没有的就为空

# join='inner' 得到交集
pd.concat([df1,df2], axis=1, join='innner')

# keys 参数,还没看明白

# ignore_index=True,如果只是简单的合并拼接而不考虑索引问题。
pd.concat([df1,df2],ignore_index=True)


合并重复数据

针对可能有索引全部或者部分重叠的两个数据集

填充因为合并时索引赵成的缺失值

where函数

#where即if-else函数
np.where(isnull(a),b,a)


combine_first方法

#如果a中值为空,就用b中的值填补
a[:-2].combine_first(b[2:])

#combine_first函数即对数据打补丁,用df2的数据填充df1中的缺失值
df1.combine_first(df2)


重塑层次化索引

stact:将数据转为长格式,即列旋转为行

unstack:转为宽格式,即将行旋转为列

result=data.stack()
result.unstack()


长格式转为宽格式

pivoted = data.pivot('date','item','value')

#前两个参数分别是行和列的索引名,最后一个参数则是用来填充dataframe的数据列的列名。如果忽略最后一个参数,得到的dataframe会带有层次化的列。


透视表

table = df.pivot_table(values=["Price","Quantity"],
index=["Manager","Rep"],
aggfunc=[np.sum,np.mean],
margins=True))

#values:需要对哪些字段应用函数
#index:透视表的行索引(row)
#columns:透视表的列索引(column)
#aggfunc:应用什么函数
#fill_value:空值填充
#margins:添加汇总项

#然后可以对透视表进行筛选
table.query('Manager == ["Debra Henley"]')
table.query('Status == ["pending","won"]')


移除重复数据

# 判断是否重复
data.duplicated()`

#移除重复数据
data.drop_duplicated()

#对指定列判断是否存在重复值,然后删除重复数据
data.drop_duplicated(['key1'])


交叉表

是一种用于计算分组频率的特殊透视表.

注意,只对离散型的,分类型的,字符型的有用,连续型数据是不能计算频率这种东西的。

pd.crosstab(df.col1, df.col2, margins=True)


类似vlookup函数

利用函数或映射进行数据转换

#1.首先定义一个字典
meat_to_animal={
'bacon':'pig',
'pulled pork':'pig',
'honey ham':'cow'
}

#2.对某一列应用一个函数,或者字典,顺便根据这一列的结果创建新列
data['new_col']=data['food'].map(str.lower).map(meat_to_animal)


替换值

data.replace(-999,np.na)

#多个值的替换
data.replace([-999,-1000],np.na)

#对应替换
data.replace([-999,-1000],[np.na,0])
#对应替换也可以传入一个字典
data.replace({-999:np.na,-1000:0})


离散化

#定义分割点
bins=[20,40,60,80,100]

#切割
cats = pd.cut(series,bins)

#查看标签
cats.labels

#查看水平(因子)
cats.levels

#区间计数
pd.value_count(cats)

#自定义分区的标签
group_names=['youth','youngAdult','MiddleAge','Senior']
pd.cut(ages,bins,labels=group_names)


分位数分割

data=np.random.randn(1000)
pd.qcut(data,4)  #四分位数

#自定义分位数,包含端点
pd.qcut(data,[0,0.3,0.5,0.9,1])


异常值

#查看各个统计量
data.describe()

#对某一列
col=data[3]
col[np.abs(col)>3]

#选出全部含有“超过3或-3的值的行
data[(np.abs(data)>3).any(1)]

#异常值替换
data[np.abs(data)>3]=np.sign(data)*3


抽样

#随机抽取k行
df.take(np.random.permutation(len(df))[:k])

#随机抽取k行,但是k可能大于df的行数
#可以理解为过抽样了
df.take(np.random.randint(0,len(df),size=k))


数据摊平处理

#对摊平的数据列增加前缀
dummies = pd.get_dummies(df['key'],prefix='key')

#将摊平产生的数据列拼接回去
df[['data1']].join(dummies)


字符串操作

# 拆分
strings.split(',')

#根据正则表达式切分
re.split('\s+',strings)

# 连接
'a'+'b'+'c'...
或者
'+'.join(series)

# 判断是否存在
's' in strings`
strings.find('s')

# 计数
strings.count(',')

# 替换
strings.replace('old','new')

# 去除空白字符
s.strip()


正则表达式

正则表达式需要先编译匹配模式,然后才去匹配查找,这样能节省大量的CPU时间。

re.complie:编译

findall:匹配所有

search:只返回第一个匹配项的起始和结束地址

match:值匹配字符串的首部

sub:匹配替换,如果找到就替换

#原始字符串
strings = 'sdf@153.com,dste@qq.com,sor@gmail.com'

#编译匹配模式,IGNORECASE可以在使用的时候对大小写不敏感
pattern = r'[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}'
regex = re.compile(pattern,flags=re.IGNORECASE)

#匹配所有
regex.findall(strings)

#使用search
m = regex.search(strings)  #获取匹配的地址
strings[m.start():m.end()]

#匹配替换
regex.sub('new_string', strings)


根据模式再切分

将模式切分,也就是将匹配到的进一步切分,通过pattern中的括号实现.

pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\\.([A-Z]{2,4})'
regex = re.compile(pattern)
regex.findall(strings)

#如果使用match
m=regex.match(string)
m.groups()

#效果是这样的
suzyu123@163.com --> [(suzyu123, 163, com)]

#获取 list-tuple 其中的某一列
matches.get(i)


分组聚合,计算

group_by技术

# 根据多个索引分组,然后计算均值
means = df['data1'].groupby([df['index1'],df['index2']).mean()

# 展开成透视表格式
means.unstack()


分组后价将片段做成一个字典

pieces = dict(list(df.groupby('index1')))

pieces['b']


groupby默认是对列(axis=0)分组,也可以在行(axis=1)上分组

语法糖,groupby的快捷函数

df.groupby('index1')['col_names']
df.groupby('index1')[['col_names']]

#是下面代码的语法糖
df['col_names'].groupby(df['index1'])

df.groupby(['index1','index2'])['col_names'].mean()


通过字典或series进行分组

people = DataFrame(np.random.randn(5, 5),
columns=['a', 'b', 'c', 'd', 'e'],
index=['Joe', 'Steve', 'Wes', 'Jim','Travis'])

# 选择部分设为na
people.ix[2:3,['b','c']]=np.na

mapping = {'a': 'red', 'b': 'red', 'c': 'blue',
'd': 'blue', 'e': 'red', 'f' : 'orange'}

people.groupby(mapping,axis=1).sum()


通过函数进行分组

#根据索引的长度进行分组
people.groupby(len).sum()


数据聚合

使用自定义函数

## 对所有的数据列使用自定义函数
df.groupby('index1').agg(myfunc)

#使用系统函数
df.groupby('index1')['data1']describe()


根据列分组应用多个函数

#分组
grouped = df.groupby(['col1','col2'])

#选择多列,对每一列应用多个函数
grouped['data1','data2'...].agg(['mean','std','myfunc'])


对不同列使用不同的函数

grouped = df.groupby(['col1','col2'])

#传入一个字典,对不同的列使用不同的函数
#不同的列可以应用不同数量的函数
grouped.agg({'data1':['min','max','mean','std'],
'data2':'sum'})


分组计算后重命名列名

grouped = df.groupby(['col1','col2'])

grouped.agg({'data1':[('min','max','mean','std'),('d_min','d_max','d_mean','d_std')],
'data2':'sum'})


返回的聚合数据不要索引

df.groupby(['sex','smoker'], as_index=False).mean()


分组计算结果添加前缀

#对计算后的列名添加前缀
df.groupby('index1').mean().add_prefix('mean_')


将分组计算后的值替换到原数据框

#将函数应用到各分组,再将分组计算的结果代换原数据框的值
#也可以使用自定义函数
df.groupby(['index1','index2'...]).transform(np.mean)


更一般化的apply函数

df.groupby(['col1','col2'...]).apply(myfunc)

df.groupby(['col1','col2'...]).apply(['min','max','mean','std'])


禁用分组键

分组键会跟原始对象的索引共同构成结果对象中的层次化索引

df.groupby('smoker', group_keys=False).apply(mean)


桶分析与分位数

对数据切分段,然后对每一分段应用函数

frame = DataFrame({'col1':np.random.randn(1000),
'col2':np.random.randn(1000)})

#数据分段,创建分段用的因子
#返回每一元素是属于哪一分割区间
factor = pd.cut(frame.col1, 4)

#分组计算,然后转成数据框形式
grouped = frame.col2.groupby(factor)
grouped.apply(myfunc).unstack()


用分组的均值填充缺失值

#自定义函数
fill_mean= lambda x:x.fillna(x.mean())

#分组填充
df.groupby(group_key).apply(fill_mean)


分组后不同的数据替换不同的值

#定义字典
fill_value = {'east':0.5, 'west':-1}

#定义函数
fill_func = lambda x:x.fillna(fill_value(x.name))

#分组填充
df.groupby(['index1','index2'...]).apply(fill_func)



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: