【Python数据科学速查】Pandas等常用操作应用替代于excel数据整理
文章目录
- 一、读取数据
- 二、字段(列)|索引的属性更改
- 三、行列的结构变动
- 四、按照列条件筛选记录
- 五、列的值处理
- 六、字符串类型列的字符内容的处理
- 1.由现有的两列拼接成一个新的字段
- 2.查找子串在字符值中的位置
- 3.返回指定位置的字符
- 4.判断字符值中是否包含子串
- 5.计算子串在字符值中的出现次数
- 6.替换字符值中的子串
- 7.根据字符分割整字符串,再截取子串
- 8.其它字符串功能使用函数
- 七、构建函数公式计算字段
- 八、分组
- 九、索引——列的转换
- 十、文件存储
- CASE
一、读取数据
1.导包
import pandas as pd
2.从csv导入数据
pd.read_csv()
df=pd.read_csv('file.csv',encoding='utf')
如果文件名带中文,上述方法可能报初始化错误,使用以下方法:f=open('文件.csv')
或wirh open('文件.csv') as f:
df = pd.read_csv(f)
with open('文件.csv',encoding='utf-8') as f:
df=pd.read_csv(f)
3.从excel导入文件
pd.read_excel(file.xlsx')
df_order=pd.read_excel('file名.xlsx')
该方法接受文件名带中文
二、字段(列)|索引的属性更改
1.针对某(些)个字段(列)|索引更名
df.rename(mapper=None, index=None, columns=None, axis=None, copy=True, inplace=False, level=None)
df_order.rename(columns={'下单日期':'日期','下单小时':'小时'},inplace=True)
或
df_order.rename({'下单日期':'日期','下单小时':'小时'},axis='columns',inplace=True)
#inplace=True对原dataframe进行修改
该方法可以更改列名或行名或更改标签值类型
如果需要改的列名特别多,可以直接给df的columns属性赋值,修改全部列名
df.columns=['年','周','频道','性别','销售数量','销售金额']
三、行列的结构变动
1.在指定位置插入行
STEP1:分割
df=pd.DataFrame([list('abc'),list('anf'),list('abc'),list('fgc'),list('rbc')])
df_p1=df[:2]
df_p2=df[2:]
STEP2:添加——底部追加内容
df.append(other, ignore_index=False, verify_integrity=False, sort=None)
ser_m=pd.Series([44,55,66])
df_p1=df_p1.append(ser_m,ignore_index=True)
STEP3:合并——多个dataframe堆叠
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=None, copy=True)
该方法不仅可以上下堆叠,还可以左右堆叠
df=df_p1.append(df_p2,ignore_index=True)
或
df=pd.concat([df_p1,df_p2],ignore_index=True]
2.在指定位置插入列
df.insert(loc, column, value, allow_duplicates=False)
df.insert(7,'brand_supplier',brand_supplier)
插入的列除了源dataframe结构的序列,也可以是常量,或者空值np.nan
3.一般方法删除指定行或列(按照索引或列名)
(1). 先获取索引,再使用drop方法删除
STEP1:获取记录index
df[条件序列].index
ser[条件序列].index
del_index=df[df['subcategory'].isin(list_type)].index
ser_nor[ser_nor>1].index
STEP2:删除索引所在行
df.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')
其中:axis=0代表行,axis=1代表列
df.drop(del_index,axis=0,inplace=True)
(2). 如果条件不复杂,条件取反后赋值给原df
df=df.query('ID!=12123')
df
4.调整列序
如果仅调整某列的位置,可以取出-删除-插入
df_id = df.id
df = df.drop('id',axis=1)
df.insert(0,'id',df_id)
如果要调整的列比较繁杂,可以直接定义好列序,赋值给原df即可
df=df[['姓名','年龄','工号']]
5.去除重复记录
去除重复记录,可以用删除的一般方法,先用duplicated()找到重复数据的索引,再drop删除,也可以直接使用:df.drop_duplicates(subset=None, keep='first', inplace=False)
6.删除空行|空列
df.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
7.连接merge
merge操作类似于excel中vlookup的存在,在sql中效通join,一般会伴随这字段的新增或更改。df.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
df=df1.merge(right=df2,how='left',on=['店铺名称','日期','小时'])
8、透视
df.pivot_table(values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
df_pv_pivot=df_pv.pivot_table(index=['资讯ID','日期'],values='PV',aggfunc='sum')
参考: https://blog.csdn.net/weixin_40844116/article/details/105802193
四、按照列条件筛选记录
选取数据的方法有很多种,本节简单使用df[条件]
选取符合条件的行记录,列全部保留。
实际操作中使用索引器loc\iloc
可以灵活选取所需数据,包括列的选择,例如
df[df['ID']==12121].iloc[:,2:5]#df[条件].iloc[:,列号:列号]
等价于掩码操作
df.loc[df['ID']==12121,'标题':'编辑']#df.loc[条件,列名:列名]
也可以使用df.query()
方法取,适用于运算条件,例如:
df.query('ID==12121').loc[:,'标题':'编辑']#df.query(字符串表达式).loc[:,列名:列名]
参考 https://blog.csdn.net/weixin_40844116/article/details/105372173
参考 https://blog.csdn.net/weixin_40844116/article/details/107221706
1.单列条件筛选记录
1).筛选某列包含某字符串的记录
df[df[列名].str.contains(正则表达式)]
df[df['brand_supplier'].str.contains('.*华鼎.*')]
2).从某列筛选等于|不等于某值的记录
df[df[列名]==值]
df[df[列名]!=值]
df[df['shop_name']=='XXXTRENTA']
df[df['shop_name']!='XXXTRENTA']
3).从某列筛选等于|不等于某些值的记录
df[df[列名].isin(列表)]
df[~df[列名].isin(列表)]
list_type=['运动','美妆','男装','女装']
df[df['subcategory'].isin(list_type)]
df[~df['subcategory'].isin(list_type)]
4).找到重复的记录 | 非重复的记录-提取汇总项
(同样的记录第一次出现是非重复,之后又出现的都算重复)df[df.duplicated(subset=None, keep='first')]
df[~df.duplicated(subset=None, keep='first')]
subset是列名或列名集合,用它来定义重复,缺失默认全字段重合的数据才是重复。
#重复的记录
df_passenger[df_passenger.duplicated('店铺名称')]
#非重复的记录
df_passenger[~df_passenger.duplicated('店铺名称')]
EXTEND:
如果要提取汇总项,除了上述方法找到非重复记录后取该列,
df_passenger[~df_passenger.duplicated('店铺名称')]['店铺名称']#pandas.core.series.Series
也可以用分组groupby
汇总项索引转列后提取使用
df_passenger.groupby(by='店铺名称').count().reset_index()['店铺名称']#pandas.core.series.Series
或者df[列名].unique()
——最快捷
df_passenger['店铺名称'].unique()#numpy.ndarray
甚至可以对汇总项快速计数df[列名].value_counts()
df_passenger['店铺名称'].value_counts()#pandas.core.series.Series
5).找到空值记录
df[pd.isna(df[列名])]
等价于df[pd.isnull(df[列名])]
df[pd.isna(df['name'])]
2.多个列组合筛选
与:df[(条件列筛选序列1)&(条件列筛选序列2)]
或:df[(条件列筛选序列1)|(条件列筛选序列2)]
异或:df[(条件列筛选序列1)^(条件列筛选序列2)]
df[(df['brand_supplier'].str.contains('.*华鼎.*'))&(df['shop_name']!='XXXTRENTA')]
五、列的值处理
1.填充空值
单列填充空值df[列名].fillna(值)
全表填充空值df.fillna(值)
df['subcategory'].fillna('其它')
2.单列赋值
df[列名]=值
这里的值可以是函数应用公式(见第七节),也可以是常量
df['channel']='淘宝'
2.替换单个值和批量替换值
(1)单值替换
方法1:定位要替换的值后直接赋替换后的值:df.loc[df[列名]==被替换的值,列名]=值
df.loc[df['subcategory']=='关店','subcategory']='其它'
方法2:replace方法df.replace(to_replace=None, value=None, inplace=False, limit=None, regex=False, method='pad')
df['subcategory']=df['subcategory'].replace('关店','其它')
(2)批量替换
- 一对一
#方法一:使用列表,保证顺序对应
xlist=['A','B','C']
ylist=['a','b','c']
#for o,l in zip(xlist,ylist):
# df[列名]=df[列名].replace(o,l)
df[列名].replace(xlist,ylist,inplace=True)
#方法二:使用字典
mapdict={'A':'a','B':'b','C':'c'}
#for m in maplist:
# df[列名]=df[列名].replace(m,mapdict[m])
df[列名].replace(mapdict)
- 多对一
#条件查找,模糊替换
df.loc[pd.to_numeric(df_pp.loc[:,'年季'].str[0:2])<=17,'年季']='17年以前'
#确值替换
df['姓名'].replace(['张倩','张茜'],'张芊')
3.类型转换:日期-数值-字符串转换
主要方法有:
- pandas内置函数、
- 自定义函数、
- numpy中的强制类型交换方法
astype(dtype, order='K', casting='unsafe', subok=True, copy=True)
| b boolean
| i signed integer
| u unsigned integer
| f floating-point
| c complex floating-point
| m timedelta
| M datetime
| O object
| S (byte-)string
| U Unicode
| V void
参考:https://www.jb51.net/article/175212.htm
1)字符串类型的数据,转换成日期
对于形似日期的字符串数据,可以转换成真正的日期
- 对于单个数据:
from dateutil import parser
parser.parse(string)
from dateutil import parser
date=parser.parse('2020-6-1')
date
>>>datetime.datetime(2020, 6, 1, 0, 0)
- 对于pandas序列:
pd.to_datetime(df[列名])
pd.to_datetime(df_order['日期'],format="%Y-%m-%d")#这里format是传入的格式
或者df[列名].astype('M')
datetime64[ns]
2)日期转成指定样式的字符串
- 对于单个数据:
date.strftime(样式)
date.strftime("%Y%m%d")
>>>'20200601'
#获取当天日期
import time
time.strftime('%Y%m%d')
#或者
import datetime
datetime.date.today().strftime('%Y%m%d')
- 对于pandas序列,没有直接的转换方法,需要使用函数转换
df[列名].apply(lambda x:x.strftime(指定格式))
pd.to_datetime(df_order['日期']).apply(lambda x:x.strftime("%Y%m%d"))
或者
def dtos(x):
return x.strftime("%Y%m%d")
pd.to_datetime(df_order['日期']).apply(dtos)
3)字符串转数值
- 对于单个数据,直接
int(string)
即可 - 对于pandas序列
pd.to_numeric(df[列名])
df_order['日期']=pd.to_numeric(pd.to_datetime(df_order['日期']).apply(lambda x:x.strftime("%Y%m%d")))
或者df[列名].astype('int')
int32
4)数值转字符串
str(number)
df_order['年龄'].apply(lambda x:str(x))
或者df[列名].astype('str')
object
六、字符串类型列的字符内容的处理
这里是对字符串值的字符内容的处理,与字段内容处理不同,例如替换值,excel里面是ctrl+h,python里参考本文,可以用df[A].replace()
方法;
而本节是针对字符串内容的处理,在excel中替换字符用的是substitute函数,python里面需要df[A].str.replace()
。
- 查看这些内置方法:help(pd.Series.str)阅读英文帮助文档
- 参考文档:https://blog.csdn.net/qq_28219759/article/details/52919233
1.由现有的两列拼接成一个新的字段
df[A].str.cat(df[B])
brand_supplier=df['brand_name'].str.cat(df['supplier_name'])
2.查找子串在字符值中的位置
df[A].str.find(childstring)
df['店铺名称'].str.find('餐厅')
3.返回指定位置的字符
返回单个字符df[A].str.get(index)
df['店铺名称'].str.get(0)
返回片段用切片
df['店铺名称'].str[:3]
4.判断字符值中是否包含子串
df[A].str.contains(childstring)
df['店铺名称'].str.contains('餐厅')
5.计算子串在字符值中的出现次数
df[A].str.count(childstring)
df['店铺名称'].str.count('餐厅')
6.替换字符值中的子串
df[A].str.replace(原字符,后字符)
df['姓名'].str.replace('三','二')#将‘三替’换成‘二’
字符串中的replace一般只可以一个字符串对应一个字符串替换,不能是列表或字典。
7.根据字符分割整字符串,再截取子串
df[A].str.split(childstring)
df['姓名'].str.split('三').str[-1]
8.其它字符串功能使用函数
除了str内置方法,也可以根据需求定制处理函数,通用的函数方法具体见下节。
1)根据字符分割整字符串,截取子串
split()
分割字符串,分割后生成子字符串列表,根据列表索引选择要截取的部分
df['姓名'].apply(lambda x:x.split('三')[-1])
2)字符大小写
小写lower()
大写upper()
df_passenger['店铺名称'].apply(lambda x:x.lower())
df_passenger['店铺名称'].apply(lambda x:x.upper())
七、构建函数公式计算字段
上一节字符内容的处理也是计算字段,包括转换类型部分也涉及到。本节介绍更通用的函数方法处理字段值。要传入的计算对象.apply(func, axis=0, broadcast=None, raw=False, reduce=None, result_type=None, args=(), **kwds)
要传入的对象
可以是df,也可以是series、groupbySeriesfunc
可以是匿名函数或者自定义函数
1.函数写法
(1).匿名函数
df['ID'].apply(lambda x: 'Boy' if x>30000 else 'Girl')
(2).自定义函数
- 传入series
def compare(x):
if x>30000:
y='Boy'
else:
y='Girl'
return y
df['ID'].apply(compare)#传入series
- 传入df,指定方向
def dfcompare(x):
if x['ID']>30000:
y='Boy'
else:
y='Girl'
return y
df.apply(dfcompare,axis=1)#传入df,axis=1指定逐行
extend:applymap()函数,可以使公式应用于所有元素,不用指定行列方向
2.公式写法
参考 https://blog.csdn.net/weixin_40844116/article/details/107221706
常规:
#(入库金额-退供应商金额)*90天售罄/100
df_sq['收入']=(df_sq['销售']-df_sq['退货'] )* df_sq['90天均价']/100
df.eval()
:
nisq=df_sq['90天均价']
df_sq['收入']=df_sq.eval('(销售-退货)*@nisq/100')
#列名不规范,可以先定义变量
#df_sq['收入']=df_sq.eval('(销售-退货)*90天均价/100')
#报错,不能直接使用带数字的不规范列名
pd.eval()
:
#df_sq['收入']=pd.eval("(df_sq.销售-df_sq.退货 )*df_sq.90天均价/100")
#报错,【df_sq.90天均价】写法错误
八、分组
1.分组
df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, observed=False, **kwargs)
df.groupby(by=['brand_supplier','shop_name'])
2.分组聚合计算
DataFrameGroupBy.函数()
df.groupby(by=['brand_supplier','shop_name']).sum()
3.取指定列来分组聚合计算/分组聚合计算后取指定列
DataFrameGroupBy.函数()[列名]
/DataFrameGroupBy[列名].函数()
ser_nor=df_nor.groupby('brand_supplier').count()['shop_name']
或者
ser_nor=df_nor.groupby('brand_supplier')['shop_name'].count()
九、索引——列的转换
1.索引转列
groupby后,by字段会变成index,如果需要转成正常列,操作如下
索引转列reset_index()
df_nor=df.groupby(by=['brand_supplier','shop_name']).sum().reset_index()
#'brand_supplier','shop_name'原本是index,转成正常列侯,也由Series变成了dataframe
2.列转索引
列转索引set_index()
十、文件存储
1.保存到excel
pd.to_excel()
ser.to_excel()
ser[ser!=0].to_excel('G:\\work files\file.xlsx',encoding='utf')
df[df['amount']!=0].to_excel('G:\\work files\file.xlsx',encoding='utf')
2.同一文件夹文件重名时增序命名
impoert os
filepath='文件存放路径'
newfile_name='带后缀的完整文件名'
i=0
while newfile_name in os.listdir(filepath):#如果当前路径已经存在文件
i=i+1#指定增序
newfile_name='文件名'+'('+str(i)+')'+'.xlsx'#要保存的文件重命名:在文件名后加序号
#循环至没有同名文件
newfile=filepath+'\\'+ newfile_name#要保存的完整路径文件名
df.to_excel(newfile,index=None)
CASE
插入拼接列
并剔除有多个shop_name的brand_supplier重复数据
import sys
def main(inda):
import pandas as pd
df=pd.read_csv('G:\\temp files\\file.csv',encoding='utf')
#插入新字段
brand_supplier=df['brand_name'].str.cat(df['supplier_name'])#拼接两个字段成一个新字段
df.insert(7,'brand_supplier',brand_supplier)#插入新字段到dataframe
#删除“华鼎”系列重复项
del_col=df[(df.brand_supplier.str.contains('.*华鼎.*'))&(df.shop_name!='XXXTRENTA')].index#获取要删除数据的索引号(品牌供应商名包含“华鼎”且店铺不为"XXXTRENTA")
df.drop(del_col,axis=0,inplace=True)#删除获得的索引号所在行记录
#获得有重复店铺数据的品牌供应商
df_nor=df.groupby(by=['brand_supplier','shop_name']).sum().reset_index()#多维度分组,随意指定一个计算行数sum(),方便将index'brand_supplier','shop_name'转为DataFrame普通列
ser_nor=df_nor.groupby('brand_supplier').count().shop_name#取到分组序列,索引号是分组依据字段'brand_supplier'
dup_list=list(ser_nor[ser_nor>1].index)#筛选计数大于1即店铺有多个的'brand_supplier'的列表
#删除多余店铺
for bs in dup_list:
shnm_list=list(df[df.brand_supplier==bs].groupby('shop_name').count().reset_index().shop_name)#多店铺的brand_supplier下的各shop_name列表
brnm=df[df.brand_supplier==bs].brand_name.iloc[0]#brand_supplier对应的brand_name(唯一),所以只要取一个就行
#逻辑:如果多个店铺名中至少有跟品牌同名的,那就将该brand_supplier下店铺名不等于品牌的数据删掉(保留店铺名与品牌有同名关系的店铺)
if brnm.lower() in [shlw.lower() for shlw in shnm_list]:#忽略大小写需要同时转大写或小写才能比较
for sn in shnm_list:#将shop_name和brand_name对比
if sn.lower()!=brnm.lower():#如果shop_name和brand_name不能完全相等
del_col_sh=df[(df.brand_supplier==bs)&(df.shop_name==sn)].index#那就找到该brand_supplier下的该shop_name
df.drop(del_col_sh,axis=0,inplace=True)#删除
#逻辑:如果店铺名没有一个与品牌名同名,那就只保留subcategory不为空的店铺
else:
list_type=['运动','美妆','男装','女装'']
del_col_su=df[(df.brand_supplier==bs)&(~df['subcategory'].isin(list_type))].index#找到该brand_supplier下subcategory不为列表中项的数据,就是subcategory空
df.drop(del_col_su,axis=0,inplace=True)
#导出所需透视图
df.subcategory=df.subcategory.fillna('其它')#空值和关店改成其它
df.loc[df.subcategory=='关店','subcategory']='其它'
ser=df.groupby(['shop_name','subcategory']).sum().amount#df.groupby(['shop_name','subcategory'])['amount'].sum()
ser[ser!=0].to_excel('G:\\work files\\file'+str(inda)+'.xlsx',encoding='utf')#取值为不为0的项
if __name__=='__main__':
main(sys.argv[1])
本文地址:https://blog.csdn.net/weixin_40844116/article/details/107041313
上一篇: 魔芋可以凉拌着吃吗?魔芋是什么季节的?
下一篇: Ubuntu安装并行Lammps