【数据分析2Pandas】

导入数据

.csv格式

常用编码utf-8,gbk,gbk2312等,gbk是中文编码,utf-8是默认编码。

第一种:

import pandas as pd
import os
os.chdir(r'./data')#数据存放路径(改为)
df = pd.read_csv('农户贷款信息大全.csv',encoding = 'gbk')#读取CSV时,如果文件有中文,会报错 
df = pd.read_csv('farmer_loan.csv',encoding =  'gbk', dtype = {'户主身份证号':str,'行政区划':str})#默认将第一行作为表头
data=pd.read_csv(r'./data/food.csv',
                dtype={'store_nbr':'category','sales':'float'})

第二种:

import csv
data=[]
f=open(r'./data/身份.csv',encoding='gbk')
files=csv.reader(f)
header=files._next_()#表头不用读
for line in files:
    data.append(line)
header
df=pd.DataFrame(data,columns=header)

data.head(5)前5行
data.tail(4)后4行
data.values返回对象所有元素的值
data.index返回行索引
data.info()数据信息
data.dtypes数据类型float/int
data.shape几行几列
data.ndim维数
data.size数据个数
data.columns列名
col_names=data.columns.tolist()将列标签转化为列表
data['age'].unique()数据有哪几种年龄
data.describe()数值型变量的描述性统计
data.describe(include='object')描述性统计,包括分类型变量
farmer_loan.describe(include='all') 输出所有变量类型统计信息
data['授信金额'].astype(float)转化为浮点数
X_train.sample(10)随机抽10个样本
df=data.sample(n=5000,replace=True)有放回抽样
df=data.sample(frac=0.1,replace=True)抽10%的样本

df.sample(n=None, frac=None, replace=False, weights=None, random_state=None, axis=None)

参数:

n——要抽取的行数。(例如n=20000时,抽取其中的2W行);

frac——抽取的比列。(有一些时候,我们并对具体抽取的行数不关系,我们想抽取其中的百分比,这个时候就可以选择使用frac,例如frac=0.8, 就是抽取其中80%);

replace——是否为有放回抽样,取replace=True时为有放回抽样

weights——每个样本的权重;

random_state——随机数种子;

axis——选择抽取数据的行还是列。axis=0的时是抽取行,axis=1时是抽取列(也就是说axis=1时,在列中随机抽取n列,在axis=0时,在行中随机抽取n行)。

打印信息:

print('农户基本数据的个数:', basic.size)
print('农户基本数据的维度个数为:', basic.ndim)
print('农户基本数据的形状为:', basic.shape)

excel格式

第一种:

df1=pd.read_excel(r'./data/身份.xls',
                 dtype={'行政区划':'str'},sheet_name=0)
df1 = pd.read_excel('农户户主基本信息全.xls',encoding = 'utf-8',sheet_name = 'Sheet1') #gbk是中文编码,utf-8是默认编码或者常用编码

basic = pd.read_excel('农户户主基本信息全.xls',encoding = 'utf-8',sheet_name = 'Sheet1',dtype= {'行政区划':str})# gbk是中文编码,utf-8是默认编码
farmer_loan = pd.read_excel('农户贷款信息大全.xls', sep=',',encoding = 'gbk',dtype = {'户主身份证号':str,'行政区划':str})

第二种循环读取多个工作表

import xlrd
workbook=xlrd.open_workbook(r'./data/身份.xls')
sheet_name=workbook.sheet_names()#文件的工作表
basic=pd.DataFrame()
for i in sheet_name:
    basic_i=pd.read_excel(r'./data/身份.xls',header=0,sheet_name=i)
    basic=pd.concat([basic,basic_i],axis=0,ignore_index=True)

遍历读取一个文件夹下,多个表,并纵向拼接

SARS人口文件里面, 合并数据,并且增加一列,表明每个数据的来源

import os
os.chdir(r'/Python/数据分析篇/data/SARS')#请自行修改路劲
files = os.listdir(r'/Python/数据分析篇/data/SARS') #查看有路劲下的文件
df_total = pd.DataFrame()
for i in files:
    df = pd.read_csv(i)
    i = i.strip('.csv')
    df['数据来源'] = i
    df_total = pd.concat([df_total,df],axis=0,ignore_index = True)

在这里插入图片描述

保存数据to_csv等

df.to_csv('./data/a1.csv', index = False,encoding='utf-8')  # 不写出索引列
df1.to_excel('./data/a1.xlsx', sheet_name='a1', index= False,encoding='utf-8')#建议保存时,尽量保证编码是utf-8或者gbk中文编码

数据库

#导入相关库
import pymysql
from sqlalchemy import create_engine
# 按实际情况依次填写MySQL的用户名、密码、IP地址、端口、数据库名
conn=create_engine('mysql+pymysql://user:passward@IP:3306/test')#user用户名,passward密码,IP服务区IP,3306端口号,test数据库名称
# 读取数据
sql = 'select * from meal_order_info'  #选择数据库中表table名称
df1 = pd.read_sql(sql,conn)
#df1 是个dataframe格式
try:
    df1.to_sql('testdf',con = conn, index= False,if_exists= 'replace')
except:
    print('error')

#保存数据
df.to_sql(name,con=engine,if_exists='replace/append/fail',index=False)#name表名,con连接,if_exists表如果存在怎么处理,append追加,replace替换原表,fail什么都不干

DataFrame格式

import numpy as np
arr1=np.array([['张三',23,'男'],['李四',27,'女'],['王二',26,'女']])
df3=pd.DataFrame(arr1,columns=['姓名','年龄','性别'],
                 index=['a','b','c'])

切片

data[:10]#前10行
data['age'][:5]
data[['age','salary']][:5]
nob_col=data['NDB_No']#取1列
columns=data[['Zinc_(mg)','Copper_(mg)']]#取多列
data[data['劳动人数']==4]
data[['户主姓名','身份证号码','性别']][data['劳动人数']==4]

索引

loc&iloc

data.loc[3:6]#名为3,4,5,6的行
age_83=titanic['survival'].loc[83,'Age']#行为83的年龄
data.loc[:,['姓名','身份证号码','性别']]
data.loc[:,'户主姓名':'薪资']#左右都可取
data.loc[data['婚姻状况']=='已婚']
data.loc[data['婚姻状况']=='已婚',['户主姓名','身份证号码','性别','婚姻状况']]
data.loc[('中国移动','iPhone13'),:]
data.loc[('中国移动',['iPhone13','iPhone12 Plus']),:]
data.iloc[:,1:4]#1:4左闭右开,索引
data.iloc[:,[0,2]]#第1列第3列
data.iloc[2:7,[1,5]]
data.iloc[0:3]#前3行

逻辑索引

|
&
~

data[['户主姓名','身份证号码']][(data.健康状况=='良好')|(data.劳动人数==4)]
basic[['户主身份证号','性别']][(basic.健康状况== '良好') & (basic['农户家庭人数'] >3)] #&代表and
data[['户主姓名','身份证号码']][~(data.婚姻状况=='已婚')]#未婚的数据
data[['户主姓名','身份证号码','劳动力人数']][data['劳动力人数'].between (4,10,inclusive=True)]
data[['户主姓名','身份证号码','健康状况']][data['健康状况'].isin(['健康','良好'])]

.set_index设置索引和.reset_index重置索引

df.reset_index(drop=True,inplace=True)
train=train.set_index('date').sort_values('asset')
train=train.set_index('date').sort_index()

两层索引

df3.loc[(a,b),:] 其中ab分别代表第一层和第二层的索引

equipment = pd.read_csv('./data/equipment.csv', header = 0,index_col=[0,1]) #使用第一列和第二列作为行索引

equipment.loc['中国移动']#第一层引用
equipment.loc['中国移动'].loc['iPhone 7'] #第二层引用

equipment.loc[('中国移动','iPhone 7'),:]#第一层引用
equipment.loc[('中国移动',['iPhone 7','iPhone 8 Plus']),:]# 第二层索引选择,多个选择
equipment.loc[(['中国移动','中国电信'],['iPhone 7','iPhone 8 Plus']),:]# 第二层索引选择,多个选择
equipment.loc[('中国移动',['iPhone 7','iPhone 8 Plus']),'客户身份证号']# 第二层索引选择,多个选择,选择对应的变量)
equipment.loc[('中国移动',['iPhone 7','iPhone 8 Plus']), ['客户手机号','客户身份证号']] #  第二层索引选择,多个选择,选择对应的变量),注意和上面的区别

运算

data['div_1000']=data['div']/1000
data['water_energy']=data['water_(g)']*data['Energy_Kcal']

insert在相应位置插入

mid=data['出生年月']
data.drop(labels='出生年月',axis=1,inplace=True)
data.insert(0,'出生年月',mid)

basic['有无劳动技能'] = np.where( basic.劳动技能.isin(['无', '0','未知'])  , '无' , '有')

del只能删除一列

del data['数据']
data.drop(labels=['敬爱老幼情况','家庭和睦情况','邻里团结情况'],axis=1,inplace=True)#axis=1改变列
data.drop(labels=[3,4],axis=0,inplace=True)#删除标签为3,4的行

改变数值

data.loc[data['是否加入农村合作社']=='未知','是否加入农村合作社']='否'
basic.loc[(basic['是否加入农民合作社']== '无') | (basic['是否加入农民合作社']== '未知'), '是否加入农民合作社'] ='否'

.rename改变列名、行标签

data.rename(columns={'出生年月': '出生日期','文化程度':'受教育水平'},index={0:'Zero',1:'One'},inplace=True)

排序df.sort_values

data.sort_values('Sodium_(mg)',inplace=True,ascending=False)
loan_info.sort_values('ye',ascending = True, na_position='first') # 升序(缺失值排最前面)

loan_info.nlargest(2,'dkje')# 查看贷款金额最大的两个
loan_info.nlargest(2,['dkje', 'ye'])# 查看贷款金额和余额最大的两个

缺失值处理

查看缺失比例,缺失值

data['Age'].isnull().sum()#缺失值个数
data[data['Age'].isnull()]#显示缺失值
data['Age'][pd.isnull(data['Age'])]#返回所有缺失值
df.apply(lambda x: sum(x.isnull())/len(x),axis= 0) #缺失比例
drop_na_columns=data.dropna(axis=1)#axis=1改变列
df.dropna(how='any',axis = 0) #只要有缺失,就删除这一行,等价于df.dropna()
new_titanic_survival=data.dropna(axis=0,subset=['Age','Sex'])#axis=0改变行
df.dropna(how-'any',subset=['户主姓名','身份证号码','birthday'],axis=0)
data[data['birthday'].isnull()][['户主姓名','身份证号码']].head(10)

填补和插值

常用的替换法有均值替换前向、后向替换和常数替换df.fillna()

df['age'].fillna(df.age.mean())#均值
df.age.fillna(df.age.median()) #中位数填补
df['婚姻状况'].fillna(df['婚姻状况'].mode()[0])#众数填补
df.fillna(value={'age':df.age.mean(),'婚姻状况':df['婚姻状况'].mode()[0],'农户家庭人数':df['农户家庭人数'].median()})
df.age.fillna(method='ffill').loc[598:600]#前向填补
df.age.fillna(method='bfill').loc[598:600]#后向填补
df.fillna(20)#常数填补
df.age.interpolate(method='polynomial',order=1)
df.age.interpolate(method='linear') #线性插值
df.fillna(value = {'Cabin':df.Cabin.mode()[0],'Age':df.Age.median()},inplace = True)

重复值处理

df[df.duplicated()]#显示重复值
np.sum(df.duplicated())#重复的总数
df.drop_duplicates()#删除重复值
df.drop_duplicates(['身份证号码'])
df.drop_duplicates(subset=['身份证号码','性别'],inplace=True)

异常值处理

异常值一般用箱线图法(分位差法)或者分布图(标准差法)来判断

在这里插入图片描述

3 σ \sigma σ

xbar=df.age.mean()
xstd=df.age.std()
print('标准差法异常值上限检测:\n',any(df.age> xbar + 3 * xstd))
print('标准差法异常值下限检测:\n',any(df.age< xbar - 3 * xstd))
df[df.age<xbar-3*xstd]#查看异常值

I Q R IQR IQR

Q1=df.age.quantitle(q=0.25)
Q3=df.age.quantitle(q=0.75)
IQR=Q3-Q1
print('箱线图法异常值上限检测:\n',any(df.age > Q3 + 1.5 * IQR))
print('箱线图法异常值下限检测:\n',any(df.age < Q1 - 1.5 * IQR))
df[df.age>Q3+1.5*IQR]

用99%/1%分位数代替异常值
一般常用分箱方法是等频分箱或者等宽分箱

sunspots.loc[sunspots['counts'] >P99,'counts_new'] = P99
sunspots.loc[sunspots['counts'] <P1,'counts_new'] = P1
#分箱
sunspots['counts_bin'] = pd.cut(sunspots['counts'],4,labels=range(4))
sunspots['counts_bin'] = pd.qcut(sunspots['counts'],w,labels=range(k))

P1=df.age.quantitle(0.01)
P99=df.age.quantitle(0.99)
df['age_new']=df['age']
df.loc[df['age']>P99,'age_new']=P99
df.loc[df['age']<P1,'age_new']=P1
df.age_new.plot(kind='box')

可视化(箱线图&直方图)

import matplotlib.pyplot as plt
%matplotlib inline
# 设置绘图风格
plt.style.use('seaborn')
df.age.plot(kind='box')

# 绘制直方图
df.age.plot(kind = 'hist', bins = 30, density = True)
# 绘制核密度图
df.age.plot(kind = 'kde')
# 图形展现
plt.show()

透视图表分组统计groupby&pivot_table

groupby

  • 数后面接groupby方法,得到分组对象
    可以对分组对象使用常用统计方法,还可以使用聚合方法aggapply
    • agg方法灵活,能够对分组对象进行相同的聚合,还可以选择不同的聚合方法
    • apply可以对分组对象使用很多函数,还可以按行计算
data.groupby('product').mean()
data.groupby('product').sum()
data[['dkje','dkqx','ye']].groupby('dkqx',as_index=True)
group=data[['product','dkje','ye','jgmc']].groupby(['product','jgmc'])
group.count()#计算样本个数
group.agg([np.sum,np.mean,np.max]).head(20)
group.agg({'ye':np.sum,'dkje':[np.sum,np.max]},)
data[['dkje','ye','yqje']].agg([np.sum,np.mean])

使用单个分组变量np.size

loan_info.groupby(by = 'product').mean()# 调用分组对象的方法,常用的用mean ,median,sum,max,min等
groupby = loan_info[['dkqx','dkje','ye','yqje']].groupby('dkqx',as_index=True)#as_index是否以分组变量作为索引

fg = df.groupby('年份')['企业'].agg([np.size,lambda x: x.nunique()])#统计每年不同的企业个数
fg.columns = ['出现的企业次数','不同企业个数'] 

在这里插入图片描述

使用多个分组变量

grouped = loan_info[['product','dkje','ye','yqje','jgmc']].groupby(by = ['product','jgmc'],as_index=True)#按照产品名和渠道进行分类统计
grouped.sum()
grouped.size()#返回每个分组的大小
grouped.count() # 计算分组的数目

使用聚合函数.agg

grouped.agg([np.mean,np.max]).head(20) #对分组后对象,计算均值和总和
grouped.agg([np.mean,np.max]).loc[('助业贷','北京业务二部'),(['ye','yqje'],'mean')] #层次化索引
grouped.agg({'ye':np.mean,'dkje':np.max}) #对2个变量分别计算不同的统计量
loan_info[['dkje','ye','yqje']].agg([np.sum,np.mean])

使用apply函数

grouped.apply(np.mean)#可以做聚合
var_name = ['yhbj', 'yhlx', 'yhfx', 'yhzg', 'yhzn']# 贷款逾期的相关字段
loan_info[var_name].apply(np.sum,axis = 0) #  相当于计算每列的均值
loan_info['sum'] = loan_info[var_name].apply(np.sum,axis=1) #  相当于计算每行的总和
loan_info[['dkje','ye']].apply(lambda x: x[0] - x[1],axis = 1) #计算每个账户的已还本金

pivot_table

passenger_survival=titanic.Survival.pivot_table(index='Pclass',values='Survival',aggfunc=np.mean)
passenger_age=titanic.Survival.pivot_table(index='Pclass',values='Age',aggfunc=np.mean)
port_stats=titanic.Survival.pivot_table(index='Embarked',values=['Fare','Survival'],aggfunc=np.sum)
age_group=pd.pivot_table(titanic,index='age_labels',values='Survival')
pd.pivot_table(data=loan_info,index='wjfl',values='ye',aggfunc=[np.sum,np.mean],margins=True,margins_name='总计')
pd.pivot_table(loan_info,index='jgmc',columns='product',values='ye',aggfunc=np.mean,fill_value=0)#fill_value=0缺失值用0填充

单个变量分组

# 单个变量分组均值
#margin =True 表示是否需要总计
pd.pivot_table(data= loan_info,index='wjfl',values='ye',\
               aggfunc=[np.sum,np.mean],margins=True,margins_name='总计')#按到5级分类计算余额的总和和均值

两层索引

pd.pivot_table(data= loan_info,index=['product','wjfl'],values='dkje',aggfunc=np.sum,margins=True,
               margins_name='总计')#两层索引

两个变量列联表

两个分类变量

# 两个变量列联表汇总
pd.pivot_table(data= loan_info,index='jgmc',columns='product',values='ye',aggfunc=np.mean,margins=True,fill_value=0,
               margins_name='总计')#用0填充缺失值

# 两个变量列联表汇总
pd.pivot_table(data= loan_info,index='jgmc',columns='product',values=['yqje','dkje'],aggfunc=np.mean,margins=True,fill_value=0,
               margins_name='总计')#用0填充缺失值

pd.pivot_table(data = df2,index ='年份',columns = '国家',values = '企业',fill_value = 0,
               aggfunc= lambda x: x.nunique())

在这里插入图片描述

列联表crosstab

交叉表更多用于计算分组频率

# 使用交叉表
#是一种计算分组频数的特殊透视表
pd.crosstab(index=loan_info['product'],columns=loan_info['wjfl'],margins=True,margins_name='总计')
pd.crosstab(index=loan_info['product'],columns=loan_info['wjfl'],margins=True,normalize='index')#normalize='index'计算行百分比,normalize='columns'计算列百分比
pd.crosstab(index =loan_info['product'], columns=loan_info['wjfl'],margins=True,normalize='columns') #index表示计算行百分比,columns表示计算列百分比
#按照行进行汇总,计算频数占比
pd.crosstab(index =loan_info['product'], columns=loan_info['wjfl'],margins=True,normalize='all')#normalize表示的是是否进行频率计算

日期格式pd.to_datatime

data['贷款发放日期']=pd.to_datatime(data['贷款发放日期'],format='%Y%m%d',errors='coerce')#errors='coerce'乱码转为空值
data['贷款发放日期'].dt.days
data['贷款发放日期'].dt.year#提取年份
data['贷款发放日期'].dt.month#提取月份
farmer_loan['贷款期限天数'] = farmer_loan['贷款期限'] / np.timedelta64(1, 'D')#天数
data['贷款发放日期']/np.timedelta64(1,'D')#天数
data['贷款发放日期']/np.timedelta64(7,'D')#周数
data['贷款发放日期']/np.timedelta64(1,'M')#月数
train['date']=train.date.dt.to_period('D')#天数
df.loc[df['birth_day'].isnull(),'birth_day'] = pd.to_datetime(  df.loc[df['birth_day'].isnull(),'出生年月'],format ='%Y%m%d',errors ='coerce')

df['age'] = pd.datetime.today().year -  df['birth_day'].dt.year
farmer_loan['贷款期限天数距离当前'] = pd.datetime.today().year  -  farmer_loan['贷款到期日期'].dt.year
# 计算客户年龄
farmer_loan['age'] =  pd.datetime.today()  - pd.to_datetime(farmer_loan['birthday'],format ='%Y%m%d',errors = 'coerce')
farmer_loan['age'] = farmer_loan['age'] /np.timedelta64(1, 'Y') #转换为年龄
farmer_loan['age'] = farmer_loan['age'].astype(int)#转化为整数

移动平均.rolling

oil['avg_oil']=oil['dcoilwtico'].rolling(7).mean()#7日移动平均
data['qsrq']=pd.to_datetime(data['qsrq'],format='%Y-%m-%d',errors='coerce')
df=data.groupby('qsrq').sum()[['dkje','ye']]
df['SMA_5']=df['dkje'].rolling(5).mean()
df['SMA_10']df['dkje'].rolling(10).mean()
df[['SMA_5','SMA_10']].plot()

shift将数据下移/上移一个单元格

df['dkje_before']  =  df['dkje'].shift(1) #将所有贷款金额进行向下平移1个单位
df['dkje_next']  = df['dkje'].shift(-1) #将所有款金额进行向上平移1个单位

diff差分

df['diff_1']=df['dkje'].diff(1)#diff(1) 代表用下一行减去上一行,例如第三行减去第二行
df['diff_2']=df['dkje'].diff(2)#diff(2) 代表用下二行减去上一行,例如第三行减去第一行

数据拼接

pd.concat()

df1=pd.DataFrame({'id':[1,2,3,4,5],'name':['张三','李四','王二','丁一','赵五'],'age':[27,24,25,23,25],'gender':['男','男','男','女','女']})#5行4列
df2=pd.DataFrame({'id':[1,2,2,4,5,6,7],'kemu':['科目1','科目1','科目2','科目1','科目2','科目3','科目1'],'score':[83,81,87,75,86,74,88]})#7行3列
df3=pd.DataFrame({'id':[1,3,5],'name':['张三','王二','赵五'],'income':[13500,18000,15000]})#3行3列
merge1=pd.concat([df1,df2],axis=1,join='inner')#axis=1改变列,join='outer’
merge2=pd.concat([df1,df2],axis=1)
basic=pd.concat([basic1,basic2,basic3],axis=0,ignore_index=True)#ignore_index=True忽略原索引

pd.merge()

左连接、右连接、全连接、内连接

merge1=pd.merge(left=df1,right=df2,how='left',left_on='id',right_on='Id')
merge2=pd.merge(left=df1,right=df2,how='right',left_on='id',right_on='Id')
merge3=pd.merge(left=df1,right=df2,how='inner',left_on='id',right_on='Id')
merge4=pd.merge(left=df1,right=df2,how='outer',left_on='id',right_on='Id')
merge5=pd.merge(left=df1,right=df2,how='left',left_index=True,right_index=True)#按索引合并,左表索引全要

apply()函数

返回前100行

def hundredth_row(column):
    hundredth_item=column.loc[99]
    return hundredth_item
hundredth_row=titanic.apply(hundredth_row)

连续值离散化

def is_minor(row):
    if row['Age']<18:
       return True
    else:
       return False
minors=titanic.apply(is_minor,axis=1)#布尔型
titanic.Age[minors]#返回未成年年龄
def generate_age_label(row):
    age=row['Age']
    if pd.isnull(age):
       return 'unknown'
    elif age<18:
       return 'minor'
    else:
       return 'adult'
age_labels=titanic.apply(generate_age_label,axis=1)
titanic['age_labels']=age_labels

统计值

group.apply(np.mean)
data[['yhbj','yhlx','ye']].apply(np.sum)

第1列-第2列

data[[‘dkje''ye']].apply(lambda x:x[0]-x[1],axis=1)

删除字符串前后空格

f1=lambda x:str(x).strip() and str(x).replace(',','')
data['授信金额']=data['授信金额'].apply(f1)

隐藏身份证隐私信息apply(lambda)

# 将身份证号码中间8位隐藏
data['身份证号码']=data['身份证号码'].apply(lambda x:x.replace(x[6:14],'********'))

apply(f)

f1 = lambda x: str(x).strip() and str(x).replace(',','')
farmer_loan['授信金额'] = farmer_loan['授信金额'].apply(f1) 
farmer_loan['授信金额'] = farmer_loan['授信金额'].astype(float)
# 对贷款发放金额和贷款余额做同样的处理
farmer_loan['贷款发放金额'] = farmer_loan['贷款发放金额'].apply(f1) 
farmer_loan['贷款余额'] = farmer_loan['贷款余额'].apply(f1) 
farmer_loan['贷款发放金额'] = farmer_loan['贷款发放金额'].astype(float)
farmer_loan['贷款余额'] = farmer_loan['贷款余额'].astype(float)

apply(lambda)

farmer_loan['ID'] = farmer_loan['户主身份证号'].apply(lambda  x: x[0:3])#取出前三位

def自定义函数

def enhance_types(df):
    for col in ['date']:
        if col in df.index:
           df[col]=pd.to_datetime(df[col],format='%Y-%m-%d')
    for col in df:
        if len(np.unique(df[col]))<=10 and col not in ['date']:
           df[col]=df[col].astype('category')
    return df
def display_statistics(df):
    display(df.dtypes)
    display(df.head(5))
    display(df.describe().T)
    display(pd.DataFrame([{col:len(np.unique(df[col])) for col in df}],index=['unique_values']))

zip处理数据

保留前4个列名,后面批量改名

columns=list(df.columns[0:4])
for i in range(34):
    columns.append('time'+str(i))
df=df.rename(columns=dict(zip(list(df.columns),columns),inplace=True))

XGBRegressor()每个特征值的贡献

model=XGBRegressor()
RFR=RandomForestRegressor(n_estimators=12,random_state=1)
rr=model.fit(X_train,y_train)
feat_labels=train[['id','date','store_nbr','family',
                   'onpromotion','dcoilwtico','holiday_type',
                   'locale_name','cluster','transactions',
                   'store_type','city']]
for feature in zip(feat_labels,rr.feature_importances_):
    print(feature)

.str字符串

函数名称说明
capitalize()返回首字母大写的字符串副本
title()返回单词首字母大写的字符串副本
lower()所有字母转化为小写
upper()所有字母转化为大写
split()返回字符串中的单词列表
strip()删除前后空格
join()返回一个字符串,该字符串是给定序列中所有字符串的连接
replace通过用指定的子字符串替换特定的子字符串
data['birthday']=data['身份证号码'].str[6:14]#切片,提取身份证号码中的日期部分
farmer_loan.loc[farmer_loan.户主身份证号 =='37XX234197806190016','birthday'] = farmer_loan['户主身份证号'].str[7:15]
#检查日期,是否以19开头
farmer_loan[~(farmer_loan['birthday'].str.startswith('19'))]
farmer_loan['户主身份证号'] = farmer_loan['户主身份证号'].str.strip('‘')#删除首尾‘
data['身份证号码'].str.strip('`')#删除首尾`
data['身份证号码'].str.strip(' ')#删除首尾空格

日期拆分

data['购药日期'] = data['购药时间'].str.split(' ').str[0]
data['购药星期'] = data['购药时间'].str.split(' ').str[1]
data['购药日期'] = pd.to_datetime(data['购药日期'], format = '%Y-%m-%d',\
    errors = 'coerce')

before:

在这里插入图片描述

after:

在这里插入图片描述

data[‘天数’] = (pd.datetime(2019,1,1) - data[‘购药日期’])/np.timedelta64(1,‘D’)距离2019年1月1日的天数

保存数据表到当前路径

.csv格式

df.to_csv(r'./data/df.csv',index=False)

excel格式

df.to_excel(r'./data/df.xls',index=False)

数据分析技巧

replace将数值转化为0,1变量

train['type']=train['type'].replace(['Holiday','Event','Bridge'],1)
data['有无劳动技能']=np.where(data.劳动技能.isin(['无','0','未知']),0,1)

insert在对应位置插入一列

df.insert(0,'date_block_num',df.apply(lambda x:
          df1[x.loc['item_id']],axis=1))

取出所有单位为(g)结尾的数据

col_names=data.columns.tolist()
gram_columns=[]
for i in col_names:
    if i.endswith('(g)'):
       gram_columns.append(i)
gram_df=data[gram_columns]

计算年龄

data['身份证号码'].str.strip('`')#删除首尾`
data['身份证号码'].str.strip(' ')#删除首尾空格
data['birthday']=data['身份证号码'].str[6:14]
data['birthday']=pd.to_datetime(data['birthday'],format='%Y%m%d',errors='coerce')
data['age']=pd.datetime.today().year-data['birthady'].dt.year
data['age']=pd.datetime.today()-data['birthday']
data['age']=data['age']/np.timedelta64(1,'Y')#岁数

map将一个表的名称(地名),连接到另一个表

df['item_category_id']=df['item_id'].map(item.set_index('item_id')['item_category_id'])

循环

for i in range(20):
    df.loc[i].plot(figsize=(10,5))

数据分布

import matplotlib.pyplot as plt
plt.style.use('seaborn')
df.age.plot(kind='hist',bins=30,density=True)#直方图
df.age.plot(kind='kde')#核密度曲线
plt.show()

pd.cut()年龄分组

pd.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False)

参数:

x——类array对象,且必须为一维,待切割的原形式;
bins——整数、序列尺度、或间隔索引。如果bins是一个整数,它定义了x宽度范围内的等宽面元数量,但是在这种情况下,x的范围在每个边上被延长1%,以保证包括x的最小值或最大值。如果bin是序列,它定义了允许非均匀bin宽度的bin边缘。在这种情况下没有x的范围的扩展;
right——布尔值。是否是左开右闭区间;
labels——用作结果箱的标签。必须与结果箱相同长度。如果FALSE,只返回整数指标面元;
retbins——布尔值。是否返回面元;
precision——整数。返回面元的小数点几位;
include_lowest——布尔值。第一个区间的左端点是否包含

  • 等距分组
df['age_bin']=pd.cut(df['age_new'],bins=5,labels=range(0,5))#0,1,2,3,4
df['age_bin'].hist()

#等宽分段
df['Age_bin'] =  pd.cut(df['Age'],5,labels=range(5))
df['Age_bin'].hist()

在这里插入图片描述

  • 按权重分组
df.age_new.max()
df.age_new.min()
w=[18,30,40,50,60,84]
df['age_bin']=pd.cut(df['age_new'],bins=w,labels=['one','two','three','four','five'])
df['age_bin'].value_counts()
  • 等频分组

pd.qcut(x, q, labels=None, retbins=False, precision=3, duplicates=’raise’)

参数:
q——整数或分位数组成的数组。整数比如 4 代表 按照4分位数进行切割;
labels——用作结果箱的标签。必须与结果箱相同长度。如果FALSE,只返回整数指标面元;
原理都是基于分位数来进行离散化

k=5
w=[i/k for i in range(k+1)]#[i/k for i in range(k+1)]=[0,0.2,0.4,0.6,0.8,1]
df['age_bin']=pd.qcut(df['age_new'],w)
df['age_bin']=pd.qcut(df['age_new'],w,labels=range(k))
df['age_bin'].hist()

# 等频分段
df['Age_bin'] = pd.qcut(df['Age'],q = 5,labels=range(5))
df['Age_bin'].value_counts().sort_index().plot(kind='bar')

在这里插入图片描述

k=5
w1=df['age_new'].quantitle([i/k for i in range(k+1)])
w1[0]=w1[0]*0.95
w1[1]=w1[1]*1.05
df['age_bin']=pd.cut(df['age_new'],w1)
df['age_bin']=pd.cut(df['age_new'],w1,right=False)#左闭右开
df['age_bin']=pd.cut(df['age_new'],w1,labels=range(k))
df['age_bin'].value_counts()
df['age_bin'].value_counts().plot(kind='bar')
  • 自定义分段标准
w = [18,30,40,50,60,82]
df['age_bin'] =  pd.cut(df['age_new'], bins =w,labels=['one','two','three','four','five'])
df['age_bin'].value_counts()

LabelEncoder将离散变量转化为0-n-1之间的数值

from sklearn.preprocessing import LabelEncoder
label_encoder=LabelEncoder()
family_labels=label_encoder.fit_transform(train['family'])
family_labels_test=label_encoder.fit_transform(test['family'])
train['family']=family_labels
test['family']=family_labels_test`	

pd.get_dummies哑变量处理离散变量

train=pd.get_dummies(train,columns=['family','year','month','day'],drop_first=True)
test=pd.get_dummies(test,columns=['family','year','month','day'],drop_first=True)

OneHotEncode哑变量处理

numerical_transformer=SimpleImputer(strategy='constant')
categorical_transformer=Pipeline(steps=[
                 ('imputer',SimpleImputer(strategy='most_frequent')),
                 ('onehot',OneHotEncoder(handle_unknown='ignore'))])
preprocessor=ColumnTransformer(
     transformers=[
     ('num',numerical_transformer,numerical_cols),
     ('cat',categorical_transformer,categorical_cols)])
model=RandomForestRegressor(n_estimators=50,random_state=0)
df=Pipeline(steps=[('preprocessor',preprocessor),('model',model)])
df.fit(X_train,y_train)
preds=df.predict(X_valid)

StandardScaler标准化处理

train_standard=StandardScaler()
train_copied=train.copy()
train_standard.fit(train_copied['onpromotion'])
train_std=pd.DataFrame(train_standard.transform(train_copied['onpromotion']))
train['onpromotion']=train_std

VIF计算

from statsmodels.stats.outliers_influence import variance_inflation_factor
vif_data=pd.DataFrame()
vif=train[['store_nbr','family','onpromotion','type','locale','locale_name','description','dcoilwtico']]
vif_data['feature']=vif.columns
vif_data['VIF']=[variance_inflation_factor(vif.values,i)for i in range(len(vif.columns))]
print(vif_data)

KNNImputer缺失值处理

from sklearn.impute import KNNImputer
X=oil['dcoilwtico'].values.reshape((203,6))
imputer=KNNImputer(n_neighbors=5,weights='distance')
z=imputer.fit_transform(X)
z=z.reshape((1218,1))
oil['dcoilwtico']=z
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值