利用python进行数据分析笔记

来源:互联网 发布:pycharm tensorflow 编辑:程序博客网 时间:2024/06/01 10:31

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和columnsDataFrame.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))

数据摊平处理

相当于将类别属性转成因子类型,比如是否有车,这个字段有3个不同的值,有,没有,过段时间买,那么将会被编码成3个字段,有车,没车,过段时间买车,每个字段用0-1二值填充变成数值型。

#对摊平的数据列增加前缀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)#使用searchm = 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)#如果使用matchm=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'])# 选择部分设为napeople.ix[2:3,['b','c']]=np.namapping = {'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)
1 0