pandas:数据处理、计算、聚合、时间序列

文章目录

  • 1. 数据记录抽取(筛选)
  • 2. 删除:drop_duplicates、drop、dropna
  • 3. 索引的堆:stack、unstack
  • 4. 一些字符串类型字段处理方法:strip、replace、split、cat等
  • 5. 数据聚合:pivot_table、groupby、concat、append、merge
  • 6. 数据映射:map、apply、applymap、transform
  • 7. index一些操作:reset_index、set_index、reindex
  • 8. 分箱:cut、qcut
  • 9. null的一些函数:isnull、notnull、fillna
  • 10. DataFrame.to_dic:转化为字典
  • 11. 其他一些常用函数/方法:sort_values、value_counts、rank、unique、rename
  • 12. 常用计算函数
  • 13. 时间序列:timestamp.dt、timestamp、to_datetime、date_range、timedelta

使用环境:python3.7+win10+pandas:0.23.4,不同版本可能存在些许差异。
pandas文件读取切片索引,请转楼:
https://blog.csdn.net/me_to_007/article/details/89818508

'''导入模块取别名为:pd,下面的df指的是DataFrame'''
import pandas as pd

'''案例中可能会设计到这个模块,如果出现np,代表的是numpy模块。'''
import numpy as np	

1. 数据记录抽取(筛选)

df[condition]
condition参数:过滤条件
返回值:DataFrame
常用condition:

  • 比较运算:==,<,>,>=,<=,!= 如:df[df.列名<1000]
  • 范围运算:
    • between:数值筛选区间
    '''筛选column_name属性0-1000的数据记录'''
    df[df.column_name.between(0,1000)]
    
    • == isin:在区域范围内==
      类似与sql的where in语句,可以传入Series,list,tuple,set等。如果想表示not in 的话,可以在condition前面加上‘~’符号。
    df[df.column_name.isin(df1.column_name)]
    '''df中columns_name属性不在df1这列数据里边的数据记录。'''
    df[~df.column_name.isin(df1.column_name)]	
    '''这么写,也可以表示not in'''
    df[df.column_name.isin(df1.column_name)==False]
    
    • isnull:空值运算
    '''筛选df的column_name属性为空的数据记录'''
    df[df.column_name.isnull()]
    
    • contains:字符匹配,筛选包含‘包含文字’的数据记录
      Series.str.contains(pat, case=True, flags=0, na=nan, regex=True)
      参数:
    • pat:字符串或者正则表达式;
    • case:如果为True,区分大小写;
    • flags:正则标记,标记传入到re模块,比如re.IGNORECASE,就是re.compile中的flags参数。
    • regex:为True时,表示pat为正则表达式。
    df[df.column_name.str.contain('包含文字'),na = False]
    
    • 逻辑运算符
      |:或;&:并且;not:非;
    '''筛选语文大于80分且数学大于70分的数据记录'''
    df[(df.语文>80) & (df.数学<70)]
    
    • 字段类型筛选
    # 筛选字段为object类型的列数据
    df.select_dtypes(['object'])
    # 筛选为数值型列的数据
    df.select_dtypes(['number'])
    # 筛选为整数列的数据
    df.select_dtypes(include=['int'])
    

2. 删除:drop_duplicates、drop、dropna

2.1 drop_duplicates:删除重复数据
df.drop_duplicates(subset=None, keep=‘first’, inplace=False)
参数:
subset:删除重复列标签,默认为所有列,也可以以列表传入部分字段名。
keep:first保留第一次出现的、last保留最后出现的、False所有重复的都会被标记重复。
inplace:Fasle不再源数据上做更改,需要赋值给其他变量。True直接在源数据上删除重复数据条。

df = pd.DataFrame({'姓名':['张三','李四','张三'],'科目':['语文','数学','语文'],'成绩':[70,85,77]})
df.drop_duplicates(['姓名','科目'],keep='last',inplace=True)
print(df)

输出如下:
姓名 科目 成绩
1 李四 数学 85
2 张三 语文 77
2.2 drop:删除
DataFrame.drop(labels = None,axis = 0,index = None,columns = None,level = None,inplace = False,errors =‘raise’ )
参数:

  • labels:单个标签或类似列表,要删除的索引或列标签。
  • axis:删除行还是删除列,{0或’index’,1或’columns’},默认为0,删除行。
  • index,columns : 单个标签或类似列表,直接指定索引或者列标签删除。效果等同于:labels+axis参数
  • level : int或level name,可选;对于MultiIndex(复合索引),将从中删除标签的级别。
  • inplace:是否在原数据集上做删除,默认为False,可以赋值给其他变量。
  • errors:错误忽略或者提示,可选:{‘ignore’, ‘raise’};默认为raise报错提示。如果忽略,则在数据有的标签上做删除。
df = pd.DataFrame({'姓名':['张三','李四','张三'],'科目':['语文','数学','语文'],'成绩':[70,85,77]})
'''删除张三记录'''
df1 = df.drop(index=[0,2])
'''没有索引10,添加errors参数'''
df2 = df.drop(labels=[0,2,10],axis=0,errors='ignore')

df1和df2两者效果是等同的,效果如下:
姓名 科目 成绩
1 李四 数学 85

2.3 dropna:删除空值
DataFrame.dropna(axis = 0,how = ‘any’,subset=None,inplace=False)
参数:

  • axis和inplace参数和drop方法是一样的。
  • how:any或者all,any表示指定轴有一个为空值则删除,all表示指定轴所有为空才删除。
  • subset:标签,指定axis轴,这些轴标签范围内再根据how参数去删除行或者列。
df = pd.DataFrame({'姓名':['张三','李四','张三'],'科目':['语文',None,'语文'],'成绩':[70,85,None]})
df1 = df.dropna(axis=0,subset=['姓名','科目'],how='any')
df2 = df.dropna(axis=1,subset=[0,1],how='any')

df1效果如下:
姓名 科目 成绩
0 张三 语文 70.0
2 张三 语文 NaN
df2效果如下:
姓名 成绩
0 张三 70.0
1 李四 85.0
2 张三 NaN


3. 索引的堆:stack、unstack

3.1 stack:列索引转化为行索引
索引level默认时从-1开始的,-1代表里层索引。
DataFrame.stack(level = -1,dropna = True )

df = pd.DataFrame(np.random.randint(50,96,size=(3,6)),
index=['张三','李四','王五'],
columns=[['java','java','html5','html5','python','python'],	['期中','期末','期中','期末','期中','期末']])
# 类似于excel的逆透视,stack方法后可以使用reset_index方法把index变成column
df1 = df.stack()

df内容:
java html5 python
期中 期末 期中 期末 期中 期末
张三 79 63 62 68 56 75
李四 83 87 62 87 75 56
王五 87 79 61 74 61 93
df1内容:
将列索引转化为index,dropna为True如果转化存在空的行,则删除。
html5 java python
张三 期中 62 79 56
期末 68 63 75
李四 期中 62 83 75
期末 87 87 56
王五 期中 61 87 61
期末 74 79 93
3.2 unstack:行索引转化为列索引

#我们把姓名索引转化为列索引,姓名在从里到外第二层索引,level从-1开始,这里level设置为0
df2 = df1.unstack(level=0)

df2内容如下:
html5 java python
张三 李四 王五 张三 李四 王五 张三 李四 王五
期中 62 62 61 79 83 87 56 75 61
期末 68 87 74 63 87 79 75 56 93


4. 一些字符串类型字段处理方法:strip、replace、split、cat等

4.1 DataFrame.str.strip
同字符串的strip方法:默认去除两边的空,去除其他字符串可以以参数传入,比如去除两遍空格和换行,lstrip和rstrip左右去除,该函数页适用于Series。

str_test = ' \n苹果\t'
'''去除两边空格,制表符,换行符'''
out_str = str_test.split(' \n\t')
#out_str:苹果
df[columns_name] = df[column_name].str.split( \n\t)

4.2 DataFrame.str.replace
使用跟字符串使用方法一样,还可以同时替换做个字段某些文本为替换文本,该函数页适用于Series。该方法第一个参数pat默认是使用正则表达式,如果只想表示字符串,可以设置regexp参数为False;

'''体育字段的‘作弊’和军训字段的‘缺考’替换为0'''
df.replace({'体育':'作弊','军训':'缺考'},0)

'''把df中的‘一箱’替换成‘1箱’,‘二箱’替换成‘2箱’,可在不同字段的值,regexp=True表示字典的key是正则表达式,不然要完全匹配才能替换。'''
df.replace({'一箱':'1箱','二箱':'2箱'},regex=True)

'''第一个参数默认是正则表达式'''
s3.str.replace('^.a|dog', 'XX-XX ', case=False)

'''pat参数还可以接受re.complie编译对象'''
regex_pat = re.compile(r'^.adog', flags=re.IGNORECASE)
s3.str.replace(regex_pat, 'XX-XX ')
'''直接传入flags参数会报错。'''		

4.3 Series.split(sep,expand=True)
按照分割符分列 expand=True转化为DataFrame,不然那只是一个数组,逗号间隔。再用concat合并即可。n参数是切割字数,默认最大。

newdf = df.column_name.str.split('|',expand=True,n=2)
'''使用get访问切分后的元素'''
s2.str.split('_').str.get(1)

4.4 cat:连接函数
参数:sep连接分隔符;na_rep:指定空值,默认None;第一个参数传入跟序列长度一样常的列表时,表示将两个序列合并。join参数:left,right,inner,outer。类似于sql连接,根据索引合并两个序列;
4.5 其他字符串处理函数摘要

  • cat(): 连接字符串
  • rsplit(): 在字符串末尾的分隔符上拆分字符串
  • get(): 索引到每个元素(检索第i个元素)
  • join(): 使用传递的分隔符连接Series的每个元素中的字符串
  • get_dummies(): 在分隔符上拆分字符串,返回虚拟变量的DataFrame
  • contains(): 如果每个字符串包含pattern / regex,则返回布尔数组
  • replace(): 将pattern / regex / string的出现替换为其他字符串或给定事件的可调用的返回值
  • repeat(): 重复值(s.str.repeat(3)相当于)x * 3
  • pad(): 在字符串的左侧,右侧或两侧添加空格
  • center(): 相当于 str.center
  • ljust(): 相当于 str.ljust
  • rjust(): 相当于 str.rjust
  • zfill(): 相当于 str.zfill
  • wrap(): 将长字符串拆分为长度小于给定宽度的行
  • slice(): 切割系列中的每个字符串
  • slice_replace(): 用传递的值替换每个字符串中的切片
  • count(): 计算模式的出现次数
  • startswith(): 相当于str.startswith(pat)每个元素
  • endswith(): 相当于str.endswith(pat)每个元素
  • findall(): 返回每个字符串的所有出现的pattern / regex的列表
  • match(): 调用re.match每个元素,将匹配的组作为列表返回
  • extract(): 调用re.search每个元素,为每个元素返回一行DataFrame,为每个正则表达式捕获组返回一列
  • extractall(): 调用re.findall每个元素,返回DataFrame,每个匹配一行,每个正则表达式捕获组一列
  • len(): 计算字符串长度
  • rstrip(): 相当于 str.rstrip
  • lstrip() 相当于 str.lstrip
  • partition() 相当于 str.partition
  • rpartition() 相当于 str.rpartition
  • lower() 相当于 str.lower
  • upper() 相当于 str.upper
  • find() 相当于 str.find
  • rfind() 相当于 str.rfind
  • index() 相当于 str.index
  • rindex() 相当于 str.rindex
  • capitalize() 相当于 str.capitalize
  • swapcase() 相当于 str.swapcase
  • normalize() 返回Unicode普通表单。相当于unicodedata.normalize
  • translate() 相当于 str.translate
  • isalnum() 相当于 str.isalnum
  • isalpha() 相当于 str.isalpha
  • isdigit() 相当于 str.isdigit
  • isspace() 相当于 str.isspace
  • islower() 相当于 str.islower
  • isupper() 相当于 str.isupper
  • istitle() 相当于 str.istitle
  • isnumeric() 相当于 str.isnumeric
  • isdecimal() 相当于 str.isdecimal

5. 数据聚合:pivot_table、groupby、concat、append、merge

5.1 concat:按照索引聚合
pd.concat
一些参数:

  • objs:需要合并的对象,可以是序列、数据框或面板数据构成的列表。[df1,df2,df3]
  • axis: {0 /‘index’,1 /‘columns’},默认为0。表示按行0或者按照列1拼接。
  • join:指定合并的方式,默认为outer,表示合并所有的数据,如果改为inner,表示合并公共部分的数据。
  • jion_axes:合并数据后,指定保留的数据轴。
  • ignore_index:bool类型的参数,表示是否忽略原数据集的索引,默认为False,如果设为True,就表示忽略原索引并生成新索引。
  • keys:为合并后的数据添加新索引,用于区分各个数据部分。
'''按照行合并,重建索引'''
df1 = pd.DataFrame(np.random.randint(3,20,(3,4)),columns=list('ABCD'))
df2 = pd.DataFrame(np.random.randint(3,20,(2,3)),columns=list('ABC'))
df3 = pd.concat([df1,df2],axis=0,ignore_index=True)

5.2 append:在尾部添加
跟列表的append方法时一样的,需要注意的时两个DataFrame字段位置,命名要一致,还是尽量使用concat方法好些。

'''ignore_index参数设置为True,忽略df1原来索引,重建索引。'''
df = df.append(df1,ignore_index = True)	

5.3 merge
这个函数效果类似于sql的连接。
需要注意的是,如果连接字段有重复数据,结果会产生笛卡尔积,不需要重复数据,请先去重。
一些参数:

  • left:指定需要连接的主表
  • right:指定需要连击的辅表
  • how:连接方式,默认为inner(内连接),其他:left(左连接),right(右连接),outer(外连接)
  • on:指定连接两张表的共同字段,如果两个表连接字段同名的话,可以指定这个,而不需要再指定left_on和right_on参数。
  • left_on:指定主表需要连接的字段
  • righ_on:次表连接字段
  • left_index:bool类型参数,是否将主表中的行索引引用作表连接的共同字段,默认为False
  • right_index:bool,辅表~~使用left_index和right_index时,等同于concat列拼接,axis=1
  • sort:bool,是否对连接后的数据按照共同字段排序,默认为False;
  • suffixes:如果数据链接的结果中存在重叠的变量名,则使用格子的前缀进行区分。
'''左连接示例'''
df2 = pd.merge(df,df1,left_on='办理渠道编码',right_on='编码',how='left')

'''多个字段匹配示例'''
df1 = pd.DataFrame({'name':['alice','bob'],'class':[2,3],'age':[18,20]})
df2 = pd.DataFrame({'name':['alice','bob'],'class':[2,4],'weight':[180,200]})
df2 = df2.rename(columns={'name':'姓名'})	#我们给name改个名字
pd.merge(df1,df2,left_on=['name','class'],right_on=['姓名','class'],how='inner')
输入如下截图:

pandas:数据处理、计算、聚合、时间序列_第1张图片
5.4 pivot_table:透视表
跟excel的透视表性质是一样的。
关于部分values字段不出现在统计结果中的原因:可能是由于字段类型不一致,比如a,b字段类型是object,c,d字段类型是float,同时传入[a,b,c,d],返回统计字段可能只会出现c,d,遇到这种情况使用astype方法字段类型转化成一致;
一些参数:

  • data:指定需要构造透视表的数据集
  • values:指定需要拉入“数值”框的字段列表;
  • index:指定行索引
  • columns:指定需要拉入‘列标签’框的字段列表;
  • aggfunc:指定数值的统计函数,默认为统计均值,也可以指定numpy模块中的其他统计函数。
  • fill_value:指定一个标量,用于填充缺失值。
  • margins:bool类型参数,是否需要显示行或者列的总计值,默认为False
  • dropna:bool类型,是否需要删除整列为缺失字段,默认为True
  • margins_name:指定行货列的总计名称,默认为ALL
'''对Price求平均,对Sales求和'''
pt = pd.pivot_table(df,index='Fruits',values=['Price','Sales'],aggfunc={'Price':np.mean,'Sales':np.sum})

'''行索引:分公司,渠道;列索引:地区;计算字段:新增;计算依据:求和。'''
df1 = pd.pivot_table(df,values='新增',index=['分公司','渠道'],columns='地区',aggfunc='sum')

'''使用自定义函数,分组后去重计数'''
df = pd.DataFrame({'uin':[1,2,2,4,2,1],
	'game':['和平','王者','王者','飞车','王者','和平'],
	'pay':[10,20,30,40,50,60]}
)
def unique_count(data):
	# 自定义去重计数函数
    return len(set(data))
'''按照游戏分组,计算uv(去重计数),求和付费'''
df1 = pd.pivot_table(df,index='game',values=['uin','pay'],aggfunc={'uin':unique_count,'pay':np.sum})
print(df,df1)
#输出如下:

pandas:数据处理、计算、聚合、时间序列_第2张图片
5.5 groupby分组
df.groupby(by = [‘分类一’,‘分类二’,‘分类三’…])[‘被统计的列’].agg({列别名1:统计函数1,列别名2:统计函数2,列别名3:统计函数3…})
一些参数:

  • by:表示用于分组的字段,可以为多列。
  • []:表示分组后用于统计的字段,可以为多列。
  • agg:表示统计别名统计值的名称,统计函数用于统计数据。常用的统计函数有:size计数,sum求和,mean平均值。
'''按日期分组,对tip字段求平均,对day字段计数'''
df.groupby('day').agg({'tip': np.mean, 'day': np.size})

'''按smoker,day分组,对tip分别计数,求平均值'''
df.groupby(['smoker', 'day']).agg({'tip': [np.size, np.mean]})

'''按照班级,性别分组,统计语文分数。总分:对语文求和;人数:对语文分数计数;......'''
df.groupby(by = '班级','性别')['语文分数'].agg({'总分',np.sum,'人数':np.size,'平均值':np.mean,'方差':np.var,'标准差':np.std,'最高分':np.max,'最低分':np.min})	

'''如果指向简单求和的话,不需要使用agg方法,后面直接跟.sum()方法就可以了'''
df.groupby(by = '班级','性别')['语文分数'].sum()

'''有时候为了结果表格好看些(规整),比如导出excel文件,我们会设置索引名字为空,具体效果大家可以手动尝试下。'''
df.index.name = None

'''还可以对分组使用apply方法,只是对分组后的数据进行apply,用法跟apply一样的。'''
df1 = pd.DataFrame(np.random.randint(10,20,size=(4,2)),columns=['销售量','采购量'])
df1['水果'] = ['苹果','桔子','苹果','桔子']
print(df1)
df2 = df1.groupby('水果').apply(sum,axis=1)
print(df2)
df3 = df1.groupby('水果').apply(sum,axis=0)
print(df3)

df1输出:
pandas:数据处理、计算、聚合、时间序列_第3张图片
df2输出:
pandas:数据处理、计算、聚合、时间序列_第4张图片
df3输出:
pandas:数据处理、计算、聚合、时间序列_第5张图片

'''假设这里有一张user表,内容如下'''
'''分组后,用join将name字段用‘_’拼接起来,向apply传入自定义函数。'''
df = user.groupby('id')['name'].apply(lambda x : '_'.join(x))
print(df)

user表
pandas:数据处理、计算、聚合、时间序列_第6张图片
df
在这里插入图片描述


6. 数据映射:map、apply、applymap、transform

6.1 apply和map和applymap区别:

  • apply:针对行或者列计算
  • map和applymap:针对元素进行计算。
  • map只能用作于series,applymap可用于DataFrame,也是针对元素进行操作。
    如果是针对Series操作,三者效果是等同的。

6.2 apply
DataFrame.apply(func, axis=0)
参数:

  • func:传入的函数方法,可以传入自定义函数,传入函数时不要带括号
  • axis:{0 or ‘index’, 1 or ‘columns’},默认是0,对每一列(所有行)计算。
df = pd.DataFrame({'姓名':['张三','李四','张三'],'科目':['语文',None,'语文'],'成绩':[70,85,None]})
'''查看每一列空值的个数。'''
def sum_null(data):
	return sum(data.isnull())
'''传入匿名函数'''
df.apply(lambda x : sum(x.isnull()))
'''传入自定义函数'''
df.apply(sum_null)

6.3 applymap

'''A-J同学的成绩,60分一下标记不及格,60-80标记良好,80分以上标记优秀'''
df = pd.DataFrame(np.random.randint(40,99,size=(10,3)),columns=['语文','数学','英语'],index=list('ABCDEFGHIJ'))
'''创建分层自定义函数'''
def qut(data):
   if data < 60:
       return '不及格'
   elif data <80:
       return '良好'
   else:
       return '优秀'
   df.applymap(qut)

输出如下:
语文 数学 英语
A 不及格 优秀 不及格
B 优秀 良好 不及格
C 不及格 良好 优秀
D 优秀 不及格 良好
E 优秀 良好 不及格
F 不及格 不及格 良好
G 不及格 不及格 优秀
H 不及格 优秀 不及格
I 良好 良好 不及格
J 优秀 优秀 优秀

6.4 map、transfrom

df = pd.DataFrame(np.random.randint(40,99,size=(5,3)),columns=['语文','数学','英语'],index=list('ABCDE'))
'''对于某一列(Series)进行操作时,下面映射函数效果是等同的,这里我们还是借用上面的qut函数'''
df['语文成绩分档'] = df.语文.map(qut)
df2 = df.语文.applymap(qut)
df3 = df.语文.apply(qut)
df4 = df.语文.transform(qut)

6.5 transpose行列转置
一起放在这里吧,需要注意的是,如果index使用的是默认的数值索引,转置后,列索引会变成原来的index,可能不是我们想要的。这时候可以先使用set_index方法设置索引。

df = pd.DataFrame(np.random.randint(40,99,size=(5,3)),columns=['语文','数学','英语'],index=list('ABCDE'))
df1 = df.transopse()

df1输出如下:
A B C D E
语文 47 86 96 84 48
数学 76 45 62 97 65
英语 72 65 65 70 41


7. index一些操作:reset_index、set_index、reindex

7.1 sort_index:按照索引排序

'''按照索引降序排列:ascending排序参数.True是升序排列。'''
'''level:如果是多级索引的话需要指定按照哪级索引进行排序;'''
'''axis=0,按照index索引排序,axis=1按照columns索引排序'''
'''by是针对某一列或几列进行排序,axis=0,结合by传参,这种用法,作用等同于sort_values;'''
df.sort_index(axis= 1,ascending=False,by = None,level=0)

7.2 set_index:设置索引
DataFrame.set_index(keys, drop=True, append=False, inplace=False, verify_integrity=False)
参数:

  • keys:设置索引的字段,字符串或者列表。
  • drop:设置字段为索引后,原来字段是否删除。
  • append:等于True时,保留原索引,并添加新索引。一般原来索引就不需要了。
  • inplace:是否在原数据上做修改。
  • verify_integrity:是否对索引做重复检查,一般不用这个,影响效率,没有必要性。
df = pd.DataFrame({'姓名':['张三','李四','王五'],'成绩':[88,75,90]})
df.set_index('姓名',drop=True,inplace=True)
print(df) 

效果如下:
姓名 成绩
张三 88
李四 75
王五 90

7.3 reset_index:重置索引
DataFrame.reset_index(level = None,dorp = False,inplace = False,col_level=0)
一些参数:

  • drop参数,=False,保留原有索引到列。
  • inplace=True 修改替换。
  • level可以传入列表,用于指定index多级索引中重置索引级别
  • col_level:如果列具有多个级别,则确定如何命名其他级别。如果为None,则重复索引名称。

7.4 reindex
通过该方法可以设置索引数据顺序,如果出现原来没有的索引,则填充为None。
reindex(index = None,**kwargs)

  • 常用**kwargs参数:method = None,fill_value = np.nan:重建索引里边如果有索引原来没有则会在表里边添加,初始值为空,可用fill_value填充缺失值。
  • method参数:
    pad/ffill:用前一个非缺失值去填充该缺失值
    backfill/bfill:用下一个非缺失值填充该缺失值
    None:指定一个值取替换缺失值。
df = pd.DataFrame({'a':[1,2,3],'b':[2,2,3],'c':[3,2,1]})
df.reindex([2,0,1])	#第一参数传入列表默认修改index位置
df.reindex(columns = ['b','a','c'])	#按照参数columns传入列表顺序修改列位置

效果如下:
pandas:数据处理、计算、聚合、时间序列_第7张图片


8. 分箱:cut、qcut

8.1 cut:等宽分箱
Serise.cut(Series,bins,right = True,labels=null)
一些参数:

  • series:需要分组的数据。
  • bins:分组的依据
  • right:分组的时候右边是否闭合。
  • labes:分组的自定义标签,可以不定义。
import pandas as pd
import numpy as np
df['数学'] = np.random.randint(40,98,size=10)
bins = [df.数学.min()-1,60,70,80,df.数学.max()+1]		
labels = ['不及格','及格','良好','优秀']
demo = pd.cut(df.数学,bins = bins,labels = labels,right = False)

8.2 等深分箱:频数

lst = [6,8,10,15,16,24]
'''等深分箱:lst列表;q按照数据个数分为几等分,lables分箱对应的自定义标签。'''
pd.qcut(lst,q = 3,lables = None)

'''等宽分箱。bins参数,按照宽度区间分箱,也可以指定labels。	'''
pd.cut(lst,bins = 3)	

9. null的一些函数:isnull、notnull、fillna

dropna函数上面提及了,这里就不再重复了。
9.1 isnull:判断空

df = pd.DataFrame({'语文':np.random.randint(50,100,size=(5)),'数学':np.random.randint(50,100,size=(5)),
                '英语':np.random.randint(50,100,size=(5)),'理综':[140,None,188,190,np.nan]},
               index=['张三', '李四','王素','凌凌漆','王五'])
   print(df)

数据如下:
语文 数学 英语 理综
张三 51 96 64 140.0
李四 83 68 88 NaN
王素 89 70 66 188.0
凌凌漆 51 78 84 190.0
王五 80 78 90 NaN

'''any表示只要有一个为空就返回True,axis=1表示所有列,即针对每一行判断,如果一行中有一个为空,则返回True'''
'''相对应的all表示范围内所有都不为空,才返回True,只要有一个不是空返回False'''
df1 = df.isnull().any(axis=1)
df2 = df[df.isnull().any(axis=1)]
print(df1)
print(df2)
'''如果想查看‘理综’字段有空值的数据记录,可以这么抽取'''
df[df.理综.isnull()]
# df各列是null的个数
df.isnull().sum()
# df总null个数
df.isnull().sum().sum()

输出如下:
张三 False
李四 True
王素 False
凌凌漆 False
王五 True
df2中只有李四和王五的成绩中存在空值,所以df2返回这两条记录。
语文 数学 英语 理综
李四 83 68 88 NaN
王五 80 78 90 NaN

'''axis=0时,针对每一列进行判断,如果一列中有空,则返回True,相应的all方法,该列所有都是空才返回True'''
df1 = df.isnull().any(axis=0)
'''针对列筛选,我们用loc,列参数再传入df1'''
df2 = df.loc[:,df1]
print(df1)
print(df2)

df1中只有理综有空值
语文 False
数学 False
英语 False
理综 True
df2
理综
张三 140.0
李四 NaN
王素 188.0
凌凌漆 190.0
王五 NaN

'''查看每一列空值的个数'''
df.isnull().sum()

9.2 notnull:非空,与isnull相反
用法个isnull一样的

'''查看每一列非空单元格个数'''
df.notnull().sum()

'''针对每一列,查看是否都不为空'''
df.notnull().all(axis=0)

'''针对每一行,看是否有非空'''
df.notnull.any(axis=1)

'''筛选也是一样的,这里不再多赘述了。'''

9.3 fillna:空值填充
DataFrame.fillna(value = None,method = None,axis = None,inplace = False,limit = None)
一些参数:

  • value:用于填充孔的值(例如0),或者用于指定每个索引(对于Series)或列(对于DataFrame)使用哪个值的值的Dict / Series / DataFrame,该值不能是列表。
  • method:{‘backfill’,‘bfill’,‘pad’,‘ffill’,None},填充方法,默认无;backfill和bfill用后面一个值填充空值,pad和ffill用前面一个值填充空值。
  • axis: {0或’索引’,1或’列’},还是一样的,这个参数指的是轴。
  • inplace:是否在原数据上做修改,如果不想再原数据上修改,可以将结果赋值给另一个变量。
  • limit:如果指定method方法的话,如果有连续空值,表示填充空值的个数,如果连续空值超过limit参数,则不再填充。
'''用后一个值填充空值'''
df.fillna(method='bfill')

'''用平均数或者其他描述性统计量填充空值'''
df.fillna(df.mean())

'''也可以传入一个字典对不用列填充不同的值。'''
df.fillna({'列名一':值一,'列名二':值二})

'''如果字典‘检测值’为空,用‘检验结果’填充'''
df1.loc[df1[df1.检测值.isnull()].index,'检测值'] = df1.loc[df1[df1.检测值.isnull()].index,'检验结果']

9.4关于空值判断的一些问题
np.nan和None在DataFrame中都是numpy.float64类型,在用‘==’进行单个元素空值判断的时候,发现即使两边都是空值,输出还是False。单个元素可以使用np.isnan方法判断,Series和DataFrame可以使用isnull识别。

df = pd.DataFrame({'姓名':['张三','李四','王五'],'年龄':[np.nan,25,None]})
print(df)

pandas:数据处理、计算、聚合、时间序列_第8张图片

'''推荐使用该方法'''
np.isnan(df.at[0,'年龄'])
#out:True
'''或者:'''
if df.at[0,'年龄']:
	print(1)
#out:1

df.at[0,'年龄']
#out:nan
type(df1.at[2,'年龄'])
#out:numpy.float64
df.at[0,'年龄'] == df.at[0,'年龄']
#out:False
df.at[0,'年龄'] == np.nan
#out:False
df.at[0,'年龄'] == None
#out:False
#Pandas使用NumPy NaN(np.nan)对象表示缺失值。这是一个不等于自身的特殊 对象(类似于sql的不确定):
np.nan == np.nan
#out:False
# Python的None对象是等于自身的	
None == None 
# out:True
# 所有和np.nan的比较都返回False,除了不等于:
5 >	np.nan 	
# out:False
np.nan	>	555 
# out:False
10 != np.nan
# out:True

10. DataFrame.to_dic:转化为字典

DataFrame.to_dict(orient =‘dict’)
orient参数:
orient : str {‘dict’,‘list’,‘series’,‘split’,‘records’,‘index’}
该参数确定返回字典的类型

  • ‘dict’(默认值):像{column - > {index - > value}}这样的字典
  • ‘list’:像{column - > [values]}这样的字典
  • ‘series’:dict like {column - > Series(values)}
  • ‘split’:dict like {‘index’ - > [index],‘columns’ - > [columns],‘data’ - > [values]}
  • ‘records’:列表如[{column - > value},…,{column - > value}]
  • ‘index’:像{index - > {column - > value}}这样的字典
'''举几个例子,具体大家可以尝试看下其他效果。'''
df = pd.DataFrame({"姓名":['张三','李四'],'语文':[78,61],'数学':[89,91]})
dic_dict = df.to_dict("dict")
dic_records = df.to_dict('records')
dic_list = df.to_dict('list')
print(dic_dict,dic_records,dic_list)

输出如下:
dic_dict
{‘姓名’: {0: ‘张三’, 1: ‘李四’}, ‘语文’: {0: 78, 1: 61}, ‘数学’: {0: 89, 1: 91}}
dic_records
[{‘姓名’: ‘张三’, ‘语文’: 78, ‘数学’: 89}, {‘姓名’: ‘李四’, ‘语文’: 61, ‘数学’: 91}]
dic_list
{‘姓名’: [‘张三’, ‘李四’], ‘语文’: [78, 61], ‘数学’: [89, 91]}


11. 其他一些常用函数/方法:sort_values、value_counts、rank、unique、rename

11.1 查看数据类型及转化
查看类型:type(df),df.dtypes:df每一列的类型。
挑出所有数值型变量:

num_variables = df.columns[df.dtypes != 'object']
  • 类型转化
'''使用astype方法,参数也可以直接传入int,str,float,不用加双引号。'''
df['Name'] = df['Name'].astype(np.datetime64) 

'''对于符合日期格式的字符串,转化为日期。比如2019-1-31'''
'''此外还有to_numeric转化为数值;to_pickle转化为二进制'''
df.column_name = pd.to_datetime(df.column_name)	

11.2 value_counts:计数

s = np.random.randint(1,100,size = 100)
n_s = pd.Series(s,name = '数字')
'''normalize参数为True时,是计算百分比。默认是False计数'''
n_s.value_counts(normalize = True)	

11.3 sort_values:排序

'''按照shuxve字段排序,axis=0表示按照行排序,inplace表示是否在原数据集上操作修改。asceding=False:降序'''
df.sort_values('shuxve',axis = 0,ascending=False,inplace =True)

'''先按字段a排序再按照字段b排序;等同于sort_index(by = ['a','b'])'''
df.sort_values(by= ['a','b']'''传入两个参数,整体排序按照acending第一参数排序,第一个字段存在重复时,第二个字段按照ascending的第二个参数True排序'''
df = pd.DataFrame({'语文':[1,2,2,5],'数学':[4,6,1,9]})
df.sort_values(['语文','数学'],ascending=[False,True])

pandas:数据处理、计算、聚合、时间序列_第9张图片
11.4 rank:排名
一些参数:

  • axis:0或1,如果是0,表示在某一列(所有行)进行排名。如果是1,就是每一行数据中的排名。
  • method:默认是‘average’,当存在两个相同数据时,排名取两个的平均值。‘min’两个数值相同,两个都取小的那个排名。‘max’相同排名取大
  • asceding:当为True时,最小值为第一名。假设有两个最小值,method取‘min’,即两个都是第一。为False时,最大值为第一名,相对应的假设有两个最大值,method参数为‘max’,那两个都取第2;
s = pd.Series([10,20,10,80,12])
s.rank(ascending=True,method='min')

效果如下:
0 1.0
1 4.0
2 1.0
3 5.0
4 3.0
11.5 unique:唯一

'''is_unique判断是否唯一'''
df.index.is_unique	#index索引是否唯一
df.column_name.is_unique	#df的column_name属性的值是否唯一
df.column_name.unique()	#提取df的column_name属性的唯一值。

11.6 sample:抽样

'''抽样10个'''
df.sample(n=10)	

'''按照百分比抽样。'''
df.sample(frac = 0.01)	

11.7 value、index、columns

'''转化为数组'''
arr = df.values
brr = df.column_name.values
'''index索引'''
df.index
'''column索引'''
df.columns
'''columns索引转化为列表'''
df.columns.tolist()

11.8 rename:重命名
inplace参数:是否在原数据源上做修改,默认为False。

'''index参数和columns参数传入字典,通过字典键值对修改索引名'''
df = pd.DataFrame(np.random.randint(3,20,(3,4)),columns=list('ABCD'))
'''把columns:A索引重命名为‘列A’,修改index索引也是一样的,传入字典即可。'''
df.rename(columns={'A':'列A'})

12. 常用计算函数

可能出现的一些参数:

  • axis : {index(0),columns(1)}指定轴,0表示对于每一列进行计算。
  • skipna:是否跳过空格,默认为True
  • level:int或level name,默认为None;如果轴是MultiIndex(分层),则沿特定级别计数,折叠为系列
  • numeric_only:book,默认为None,是否仅针对只包含数值的轴进行计算。

常用函数及作用如下:

  • count:非空计数
  • sum:求和
  • mode:众数
  • mad:平均绝对偏差
  • max:最大值
  • min:最小值
  • std:标准差
  • var:方差
  • cov:协方差
  • skew:偏态系数
  • kurt:峰态系数
  • mean:平均值
  • cumsum:累加函数,该函数只能针对Series计算。
  • corr:method参数:pearson (default):标准相关系数;kendall:Kendall Tau相关系数;spearman :斯皮尔曼等级相关系数
  • quantile:样本分位数,比如0.25四分位。
  • describe:描述性统计;
    离散型变量描述性统计:df.describe(include = [‘object’])

13. 时间序列:timestamp.dt、timestamp、to_datetime、date_range、timedelta

13.1 datetime.dt:提取时间元素 ​​
​​pandas:数据处理、计算、聚合、时间序列_第10张图片

df = pd.DataFrame({'日期':['2019-2-1','2019-1-2'],'销量':[151,269]})
df['月'] = pd.to_datetime(df.日期).dt.month
df['日'] = pd.to_datetime(df.日期).dt.day
print(df)

输出如下:
在这里插入图片描述
13.2 to_datetime:字符串转化为日期
errors参数:
ignore:在日期无法解析时返回原始输入
coerce:无法解析时转化为NaT(not a time)

import datetime
dti = pd.to_datetime(['1/1/2018', np.datetime64('2018-01-01'),datetime.datetime(2018, 1, 1)] , errors='ignore')
'''使用origin参数时,可以指定创建DatetimeIndex。例如,将1960-01-01作为开始日期:'''
s = pd.to_datetime([1, 2, 3], unit='D', origin=pd.Timestamp('1960-01-01'))
print(s)

s输出如下:
DatetimeIndex([‘1960-01-02’, ‘1960-01-03’, ‘1960-01-04’], dtype=‘datetime64[ns]’, freq=None)
13.3 date_range:固定频率生成日期
一些参数:

  • start:开始日期,用字符串
  • end:结束日期,用字符串
  • freq:间隔,其他参数需要进一步查询
  • periods:没有指定结束日期,可以指定该参数说明生成日期个数。
dti = pd.date_range('2018-01-01', periods=3, freq='H')
print(dti)

dti输出如下:
DatetimeIndex([‘2018-01-01 00:00:00’, ‘2018-01-01 01:00:00’,‘2018-01-01 02:00:00’],type=‘datetime64[ns]’, freq=‘H’)
freq详参:
pandas:数据处理、计算、聚合、时间序列_第11张图片

13.4 Timestamp
该类继承于datetime.datetime

pd.Timestamp(2017, 1, 1, 12)
#Timestamp('2017-01-01 12:00:00')
pd.Timestamp(year=2017, month=1, day=1, hour=12)
#Timestamp('2017-01-01 12:00:00')

Timestamp一些属性:

t = pd.Timestamp('2019-1-1')
t.dayofweek	'''星期一到星期日:0-6'''
#4
  • day:返回日期的day
  • dayofweek :返回星期几
  • dayofyear:返回一年当中第多少天
  • days_in_month:返回当月一共有多少天
  • daysinmonth:返回当月的第多少天
  • hour :返回小时
  • is_leap_year
  • is_month_end :是否当月最后一天
  • is_month_start :是否当月的第一天
  • is_quarter_end :是否最后季度
  • is_quarter_start :是否第一个季度
  • is_year_end :是否当年最后一天
  • is_year_start :是否当年第一天
  • microsecond
  • minute :返回分钟
  • month :返回月份
  • nanosecond
  • quarter :返回季度
  • second :返回时间的秒
  • value :返回时间戳,数值型
  • weekofyear :返回一年中第多少周
  • year:返回日期的年
    一些方法:
'''strptime字符串转化为日期'''
pd.Timestamp.strptime('2019-1-1','%Y-%m-%d')
#Timestamp('2019-01-01 00:00:00')

pandas:数据处理、计算、聚合、时间序列_第12张图片
13.5 Timedelta
该类继承于datetime.timedelta
表示持续时间,两个日期或者时间之间的差异,具体大家根据nuit参数灵活使用。参数从官网copy下来的,尝试了下,可能有个别参数用不了,比如M,W。大家可以多试试。
unit参数:
str,可选,如果输入是整数,则表示输入的单位。默认为’ns’。可能的值:{‘Y’,‘M’,‘W’,‘D’,‘days’,‘day’,‘hours’,hour’,‘hr’,‘h’,‘m’,‘minute’ ,‘min’,‘minutes’,‘T’,‘S’,‘seconds’,‘sec’,‘second’,‘ms’,‘milliseconds’,‘millisecond’,‘milli’,‘millis’,’ L’,‘us’,‘microseconds’,‘microsecond’,‘micro’,‘micros’,‘U’,‘ns’,‘nanoseconds’,‘nano’,‘nanos’,‘nanosecond’,‘N’ }

friday = pd.Timestamp('2018-01-05')
print(friday.day_name())
#'Friday'

'''加一天,unit参数表示间隔时间单位'''
saturday = friday + pd.Timedelta('1 day')
print(saturday.day_name())
#'Saturday'
'''加5小时'''
dt = friday + pd.Timedelta('5 h')
print(dt)
#Timestamp('2018-01-05 05:00:00')

'''也可以这样传入参数'''
pd.Timedelta(hours=1)
#Timedelta('0 days 01:00:00')
pd.Timedelta(days=1)
#Timedelta('1 days 00:00:00')
pd.Timedelta(minutes=1)
#Timedelta('0 days 00:01:00')
pd.Timedelta(seconds=1)
#Timedelta('0 days 00:00:01')
pd.Timedelta(weeks=1)
#Timedelta('7 days 00:00:00')

'''传入datetime模块timedelta类不支持months参数,可以使用下面方法'''
from dateutil.relativedelta import  relativedelta
import datetime
a = datetime(2008,3,31)
a + relativedelta(months=-1)
#out: datetime.date(2008, 2, 29)

13.6 时间切片

rng = pd.date_range(start, end, freq='BM')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
print(ts.index)

输出如下:
DatetimeIndex([‘2011-01-31’, ‘2011-02-28’, ‘2011-03-31’, ‘2011-04-29’,
‘2011-05-31’, ‘2011-06-30’, ‘2011-07-29’, ‘2011-08-31’,
‘2011-09-30’, ‘2011-10-31’, ‘2011-11-30’, ‘2011-12-30’],
dtype=‘datetime64[ns]’, freq=‘BM’)

ts[:5].index

输出:
DatetimeIndex([‘2011-01-31’, ‘2011-02-28’, ‘2011-03-31’, ‘2011-04-29’,‘2011-05-31’],dtype=‘datetime64[ns]’, freq=‘BM’)

ts[::2].index

输出:
DatetimeIndex([‘2011-01-31’, ‘2011-03-31’, ‘2011-05-31’, ‘2011-07-29’,
‘2011-09-30’, ‘2011-11-30’],dtype=‘datetime64[ns]’, freq=‘2BM’)

'''2011年1月31日'''
ts['1/31/2011']	

'''也可以结合datetime模块直接传入datetime'''
ts[datetime.datetime(2011, 12, 25):]

'''2011年10月31日-2011年12月31日'''
ts['10/31/2011':'12/31/2011']

'''按照年筛选'''
ts['2011']	

'''按照年月筛选'''
ts['2011-6']	

'''DataFrame也是实用的,我们也可以使用loc切片'''
'''年月范围筛选,包含月最后一天'''
df['2013-1':'2013-2']
df.loc['2013-1':'2013-2',:]

'''年月日筛选'''
df['2013-1':'2013-2-28']

'''传入datetime字符串筛选''
df['2013-1':'2013-2-28 00:00:00']
	
'''精确索引:这些Timestamp和datetime物体有精确的hours, minutes,和seconds,即使没有显式指定它们(它们是0)'''
df[datetime.datetime(2013, 1, 1):datetime.datetime(2013, 2, 28)]
df[datetime.datetime(2013, 1, 1, 10, 12, 0):datetime.datetime(2013, 2, 28, 10, 12, 0)]

pandas官方文档
http://pandas.pydata.org/pandas-docs/stable/


欢迎各位分享,转载请注明出处。

你可能感兴趣的:(Python)