set_index
专门用来将某一列设置为index的方法
DataFrame.set_index(keys,drop=True,append=False,inplace=False,verify_integrity=False)
- keys:要设置为索引的列名(如有多个应放在一个列表里)
- drop:将设置为索引的列删除,默认为True
- append:是否将新的索引追加到原索引后(即是否保留原索引),默认为False
- inplace :是否在原DataFrame上修改,默认为False
- verify_integrity:是否检查索引有无重复,默认为False
df1 = pd.DataFrame({ 'year':[2012,2013,2014,2015], 'month':[1,4,6,8], 'sale':[55,44,11,33] }) print(df1) # 保留原来的列 print(df1.set_index('month',drop=False)) print(df1.set_index('month',append=True)) # 保留原来的索引列 也就是两个索引 print(df1.set_index(pd.Series(range(4)))) df1.set_index('month',inplace=True) print(df1)
去重
Pandas去重函数:drop_duplicates()
“去重"通过字面意思不难理解,就是删除重复的数据。在一个数据集中,找出重复的数据删并将其删除,最终只保存一个唯一存在的数据项,这就是数据去重的整个过程。删除重复数据是数据分析中经常会遇到的一个问题。通过数据去重,不仅可以节省内存空间,提高写入性能,还可以提升数据集的精确度,使得数据集不受重复数据的影响。
Panda DataFrame对象提供了一个数据去重的函数 drop_duplicates()
DataFrame. drop_duplicates(subset=None,keep='first', inplace=False,ignore_index=False)
- subset:表示要进去重的列名,默认为 None。
- keep:有三个可选参数,分别是 first、last、False,默认为first,表示只保留第一次出现的重复项,删除其余重复项,last表示只保留最后一次出现的重复项,False则表示删除所有重复项
- inplace:布尔值参数,默认为False表示删除重复项后返回一个副本,若为Ture则表示直接在原数据上删除重复项
df1 = pd.DataFrame({ 'year':[2012,2013,2013,2015,2016,2020,2020], 'month':[1,4,6,8,4,4,4], 'sale':[55,44,11,33,4,4,4] }) print(df1) print(df1.drop_duplicates()) # 默认情况下,他会给予所有列删除重复的列 也就是删除完全一样的两行 print(df1.drop_duplicates(subset='year')) # 设置如果year中有相同数据,那么就删掉
字符串操作
Python会处理字符串起来会很容易,作为工具包的Pandas同样可以简单快速的处理字符串,几乎把Python内置的字符串方法都给复制过来了,这种方法就是Pandas内置的str方法,通俗来说就可以将series和index对象中包含字符串的部分简单看作单个字符串处理,达到批量简单快速处理的目的
- lower()将的字符串转换为小写。
- upper()将的字符串转换为大写。. len()得出字符串的长度。
- strip()去除字符串两边的空格(包含换行符)。
- split()用指定的分割符分割字符串。
- cat(sep=“”)用给定的分隔符连接字符串元素。
- contains (pattern)如果子字符串包含在元素中,则为每个元素返回一个布尔值 True,否则为False。
- replace(a,b)将值a替换为值b。
- count(pattern) 返回每个字符串元素出现的次数
- startswith(pattern)如果 Series 中的元素以指定的字符串开头,则返回True.
- endswith(pattern)如果 Series中的元素以指定的字符串结尾,则返回True。
- findall(pattern)以列表的形式返出现的字符串。
- find(pattern)返回字符串第一次出现的索引位置。
注意:上述所有字符串函数全部适用于DataFrame对象,同时也可以与Python内置的字符串函数一起使用,这些函数在处理Series/DataFrame对象的时候会自动忽略缺失值数据(NaN)
# lower() 字符串变小写 s = pd.Series(['C','Python','java','\tgo',np.nan,'\tCshape','Android']) print(s.str.lower()) print('-------------------') # upper() 字符串变大写 print(s.str.upper()) print('-------------------') # 求字符串长度 print(s.str.len()) print('-------------------') # 去除左右两边空格 print(s.str.strip())
s = pd.Series(['C C++','Python iPython','java JavaScript','go',np.nan,'Cshape','Android']) # 对字符串以给定的符号进行分割 print(s.str.split(' ')) print('-------------------') # 对组间字符串进行拼接,以给定的符号进行拼接 print(s.str.cat(sep='---'))
s = pd.Series(['C C++','Python iPython','java JavaScript','go',np.nan,'Cshape','Android']) # contains 如果子字符串包含再某元素中,那么为每个元素返回一个布尔值,True,否则False print(s.str.contains('a')) print('-------------------') # replace(a,b) 将值a换为值b print(s.str.replace('a','AAAA'))
# count用于计算每个字符串元素出现的次数 s = pd.Series(['C','Python','java','\tgo',np.nan,'\tCshape','Android','Python','Java','java','C']) print(s.str.count(pat='Python'))
# endswith startswith 判断Series元素中以指定的元素结尾/开头,返回True s = pd.Series(['C C++','Python iPython','java JavaScript','go',np.nan,'Cshape','Android']) print(s.str.startswith('C')) print('---------------') print(s.str.endswith('a'))
pandas数据分析三板斧—map,apply,applymap
在日常的数据处理中,经常会对一个DataFrame进行逐行、逐列和逐元素的操作,对应这些操作,Pandas中的map、apply和applymap可以解决绝大部分这样的数据处理需求
三种方法的使用和区别:
apply:应用在DataFrame的行或列中;
applymap:应用在DataFrame的每个元素中;
map:应用在单独一列(Series)的每个元素中。
apply()方法
前面也说了apply方法是一般性的"拆分-应用-合并”方法。apply()将一个函数作用于DataFrame中的每个行或者列它既可以得到一个经过广播的标量值,也可以得到一个相同大小的结果数组。我们先来看下函数形式:
df.apply(func,axis=0, raw=False,result_type=None,args=(),**kwds)
- func :函数应用于每一列或每一行
- axis:
0或“索引”:将函数应用于每一列。
1或“列”:将函数应用于每一行。
df = pd.DataFrame([[4,9]]*3,columns=['A','B']) print(df) print(df.apply(np.sum)) print('------------') print(df.apply(np.sum,axis=1)) # 也可以使用lambda函数做简单的运算 print(df.apply(lambda x : x+1))
这样子的匿名函数显然有点不方便,如果函数体太长也不方便阅读,因此我们可以自己封装一个函数
def cal(df,x,y): df['C']=(df['A']+df['B'])*x df['D']=(df['A']+df['B'])*y return df print(df.apply(cal,x=1,y=2,axis=1)) print('--------------') print(df.apply(cal,args=(3,8),axis=1)) print('--------------') print(df.apply(cal,**{'x':3,'y':3},axis=1))
在这里我们先定义了一个cal 函数,它的作用是计算A.B列和的×倍和y倍添加到C,D列中。这里有三种方式可以完成参数的赋值,
第一种方式直接通过关键字参数赋值,指定参数的值;
第二种方式是使用args 关键字参数传入一个包含参数的元组;
第三种方式传入通过**传入包含参数和值的字典
applymap()函数
print(df.applymap(lambda x: '%.2f'%x)) print('---------------------') print(df[['A']].applymap(lambda x: '%.2f'%x)) # print(df['A'].applymap(lambda x: '%.2f'%x)) # 会报错这样子
需要注意的是这里必须使用df[[‘A’]],表示这是一个DataFrame,而不是一个Series,如果使用df[‘A’]就会报错。同样从行取元素也要将它先转成DataFrame。还需要注意apply方法和applymap的区别:
apply方法操作的是行或列的运算,而不是元素的运算,比如在这里使用格式化操作就会报错;
applymap方法操作的是元素,因此没有诸如axis这样的参数,它只接受函数传入。
map()方法
如果你对applymap方法搞清楚了,那么map方法就很简单,说白了map方法是应用在Series中的,还是举上面的例子:
print(df[['A']].applymap(lambda x: '%.2f'%x)) print('------------') print(df['A'].map(lambda x: '%.2f'%x))
案例分析
案例一
首先打印出整体数据进行查看分析
chipo = pd.read_csv('17-data/快餐数据.tsv',sep='\t') print(chipo.head()) print('----------------') print(chipo.info()) print('----------------') print(chipo.columns) print('----------------')
计算被下单最多的
# 计算被下单最多的 c = chipo[['item_name','quantity']].groupby('item_name',as_index=False).sum() c.sort_values('quantity',ascending=False,inplace=True) c
计算一下item_name这一列中有多少商品被下单,那么就是计算这一列中有多少不同的数据
# 计算再item_name这一列中有多少商品被下单 chipo['item_name'].nunique()
# 再choice_description中,下单次数最多的商品是失眠 # value_counts函数可以对Series里面的每个值进行计数并且排序 chipo['choice_description'].value_counts()
计算总下单数
# 总下单数? total_items_orders = chipo['quantity'].sum() total_items_orders
将某一类型转换为浮点型
# 将item_price转换为浮点数 print(chipo.dtypes) chipo['item_price'] = chipo['item_price'].str.strip('$').astype(float)
计算总收入,可以先求出每行收入,然后求和
# 在该数据集对应的时期内,收入是多少 chipo['sub_total']=round(chipo['item_price']*chipo['quantity'],2) chipo['sub_total'].sum()
计算一天中有多少订单
# 在该数据集中,一共多少订单 chipo['order_id'].nunique()
求每一单的平均价格,其实可以变为求每一行的价格,然后求每行价格的和之后再取平均
# 每一单对应的平均总价是多少 chipo[['order_id','sub_total']].groupby(by=['order_id']).sum()['sub_total'].mean()
求多少中不同类型的产品被卖出
# 一共有多少种不同的商品被售出 chipo['item_name'].nunique()
案例二(过滤和排序)
# 2012年欧洲杯决赛阶段16支球队的数据字段名称解释说明 # Team球队. # Goals进球数 # Shots on target射正次数. # Shots off target射偏次数 # Shooting Accuracy射门精确度. # Goals-to-shots 射门的得分比率. # Total shots射门次数
导入数据集
euro12 = pd.read_csv('./18-data/Euro2012_stats.csv')
查看数据集基本信息
print(euro12.info()) print(euro12.head())
# 只选取Goals进球数这一列 print(euro12['Goals']) print(euro12.Goals)
# 求参加欧洲杯的球队个数 print(euro12['Team'].nunique()) print(euro12.shape[0]) `在这里插入代码片` print(euro12.index) print(len(euro12))
# 该数据中一共有多少列? print(len(euro12.columns))
# 将数据集中的列Team,Yellow Cards 和Red Cards单独存为一个名叫discipline的数据中 discipline = euro12[['Team','Yellow Cards','Red Cards']] print(discipline)
# 对数据discipline按照先Red Cards再Yellow Cards进行排序 discipline.sort_values(['Red Cards','Yellow Cards'],ascending=False)
# 计算每个球队拿到黄牌数的平均值 round(discipline['Yellow Cards'].mean(),2)
# 找到进球数Goals超过6的球队数据 # print(euro12.Goals>6) euro12[euro12.Goals>6]
# 选取以字母G开头的球队的数据 euro12[euro12.Team.str.startswith('G')]
# 选取前7列`在这里插入代码片` euro12.iloc[:,0:7]
# 选取除了最后3列外的所有列 euro12.iloc[:,0:-3]
# 找到England Italy和Russia的射正率 euro12.loc[euro12.Team.isin(['England','Italy','Russia']),['Team','Shooting Accuracy']]
案例三(分类)
drinks = pd.read_csv('18-data/drinks.csv')
# 查看相关学习 print(drinks.info()) print(drinks.head())
# 那个大陆消耗的啤酒最多 # 如果想通过列下标去取列,需要借助iloc[行下标切片,列下标切片]这种方式 drinks[['beer_servings','continent']].groupby('continent').sum().sort_values('beer_servings',ascending=False)[0:1] drinks.groupby('continent').sum().sort_values('beer_servings',ascending=False)[0:1].beer_servings drinks.groupby('continent').sum().sort_values('beer_servings',ascending=False).head(1) drinks.groupby('continent').sum().sort_values('beer_servings',ascending=False).iloc[0:1,0:1] # 使用iloc方式
# 打印出每个大陆(continent)的红酒(wine_servings)消耗的描述性统计值 drinks.groupby('continent').wine_servings.describe() # 使用describe方法打印出描述性信息
# 打印出每个大陆每种就类别的消耗平均值 drinks.groupby('continent').mean()
# 打印出每个大陆每种酒类别的消耗中位数 drinks.groupby('continent').median()
# 打印出每个大陆对spirit消耗的平均值,最大值和最小值 drinks.groupby('continent').spirit_servings.agg(['mean','max','min'])