数学名词
离散化和面元划分 :就是分组,进行相应的计算
对于数据进行离散化和面元划分的前提条件是:连续变化的数据
例如下面是一组人的年龄数据,现在要按照年龄划分为不同年龄的4组(即把数据拆分为4个面元),
分别为“18到25”、“25到35”、“35到60”及“60以上。为了实现分组,需要使用pandas的cut函数:
pandas返回的是一个特殊的Categorical对象。你可以将其看作一组表示面元名称的字符串。实际上它含义一个表示不同分类名称的levels数组以
及一个为年龄数据进行标号的labels属性。, 以及各个阶段人的数量统计
哑变量
也叫虚拟变量,引入哑变量的目的是,将不能够定量处理的变量量化,如职业、性别对收入的影响,战争、自然灾害对GDP的影响,
季节对某些产品(如冷饮)销售的影响等等。
这种“量化”通常是通过引入“哑变量”来完成的。根据这些因素的属性类型,构造只取“0”或“1”的人工变量,通常称为哑变量,记为D。
举一个例子,假设变量“职业”的取值分别为:工人、农民、学生、企业职员、其他,5种选项,我们可以增加4个哑变量来代替“职业”这个变量,
分别为D1(1=工人/0=非工人)、D2(1=农民/0=非农民)、D3(1=学生/0=非学生)、D4(1=企业职员/0=非企业职员),
最后一个选项“其他”的信息已经包含在这4个变量中了,所以不需要再增加一个D5(1=其他/0=非其他)了。
这个过程就是引入哑变量的过程,其实在结合分析(conjoint analysis)中,就是利用哑变量来分析各个属性的效用值的。
# -*- coding: utf-8 -*-
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
'''
离散化和面元划分 :就是分组,进行相应的计算
对于数据进行离散化和面元划分的前提条件是:连续变化的数据
例如下面是一组人的年龄数据,现在要按照年龄划分为不同年龄的4组(即把数据拆分为4个面元),
分别为“18到25”、“25到35”、“35到60”及“60以上。为了实现分组,需要使用pandas的cut函数:
pandas返回的是一个特殊的Categorical对象。你可以将其看作一组表示面元名称的字符串。实际上它含义一个表示不同分类名称的levels数组以
及一个为年龄数据进行标号的labels属性。, 以及各个阶段人的数量统计
数据挖掘中有些算法,特别是分类算法,只能在离散型数据上进行分析,然而大部分数据集常常是连续值和离散值并存的。因此,
为了使这类算法发挥作用,需要对数据集中连续型属性进行离散化操作。
那么,如何对连续型属性离散化呢?常见的有等宽分箱法,等频分箱法:
等宽分箱法的思想是,将数据均匀划分成n等份,每份的间距相等。
等频分箱法的思想是,将观察点均匀分成n等份,每份的观察点数相同。
在对数据离散化前,需要先处理异常点敏感问题,即我们需要首先设定一个阈值将异常数据移除。有两种思路:
1.设定阈值为90%,将数据从小到大排序,移除全部数据最小的5%和最大的5%数据
2. 设定阈值为90%,将数据从小到大排序,然后对所有数据求和,并计算每个数据占总和的比例,移除占比10%的数据
在这里,我们实现的方法是等宽分箱法,针对连续型数据集,代码比较简单基础,在此抛砖引玉,大家可以在代码的基础上增添自己需要的功能。
'''
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
bins = [18, 25, 35, 60, 100]
cats = pd.cut(ages, bins)
#每一个数据所在的区间范围
#数据的长度
#Categories对象,包含了分组的数量以及不同分类的名称
print(cats)
# [(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
# Length: 12
# Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
#为年龄数据进行标号,比如0就是(18,25)的标号
print(cats.codes)
# [0 0 0 1 0 0 2 1 3 2 2 1]
#不同面元先的数据的数量
print(pd.value_counts(cats))
# (18, 25] 5
# (35, 60] 3
# (25, 35] 3
# (60, 100] 1
# dtype: int64
# 还可以不指定面元的界限,直接传入一个整数参数,cut()会按照指定的数字,将元素划分为相应的几部分。
cats2=pd.cut(ages,5)
print(cats2)
# [(19.959, 28.2], (19.959, 28.2], (19.959, 28.2], (19.959, 28.2], (19.959, 28.2], ..., (28.2, 36.4], (52.8, 61.0], (44.6, 52.8], (36.4, 44.6], (28.2, 36.4]]
# Length: 12
# Categories (5, interval[float64]): [(19.959, 28.2] < (28.2, 36.4] < (36.4, 44.6] < (44.6, 52.8] <
# (52.8, 61.0]]
#qcut会得到各个面元相同数量的数据点
data=np.random.randn(1000)#正态分布
cats3=pd.qcut(data,4)#按四分位数进行切割
print(pd.value_counts(cats3))
# (0.627, 3.299] 250
# (-0.0917, 0.627] 250
# (-0.748, -0.0917] 250
# (-3.593, -0.748] 250
# dtype: int64
'''
检测和过滤异常值
'''
data=DataFrame(np.random.randn(1000,4))#正态分布
print(data.describe())
# 0 1 2 3
# count 1000.000000 1000.000000 1000.000000 1000.000000
# mean -0.033081 0.058738 -0.027423 -0.028144
# std 0.976585 1.005248 1.012929 1.017619
# min -3.118296 -3.133514 -3.128117 -2.966178
# 25% -0.683512 -0.611462 -0.683149 -0.664482
# 50% -0.057522 0.033559 -0.016225 -0.051340
# 75% 0.638193 0.751441 0.692127 0.643136
# max 3.180026 3.027844 3.149158 3.694023
#找出大于3的值的行,any()用法
print(data[(np.abs(data)>3).any(1)])
# 0 1 2 3
# 126 -0.829001 -1.025659 3.160653 -0.149694
# 278 3.068706 2.759795 -0.973630 1.290398
# 298 -0.813094 -0.199006 0.877084 -3.051210
# 342 1.019925 -3.398058 1.281663 -0.924395
# 520 0.529010 -3.053272 -0.231004 0.163613
# 603 1.770662 -3.697815 -0.056443 -1.430715
# 613 -0.223834 0.899780 3.186809 0.363643
# 633 -0.247019 -4.399414 0.777015 0.449591
# 831 -0.662822 0.929492 0.637030 -3.116932
#对数据大于3的数值进行赋值
print(data[np.abs(data)>3])#data矩阵中绝对值大于3的显示小于3的显示为NaN (988 NaN NaN 3.047267 NaN)
#赋值
data[np.abs(data)>3]=np.sign(data)*3
print(data.describe())
# 0 1 2 3
# count 1000.000000 1000.000000 1000.000000 1000.000000
# mean -0.003373 -0.013148 -0.026312 -0.035093
# std 0.986391 0.999095 1.004011 0.995485
# min -3.000000 -3.000000 -3.000000 -3.000000
# 25% -0.670433 -0.691231 -0.739701 -0.715927
# 50% 0.005562 -0.017495 0.010079 -0.025116
# 75% 0.678260 0.648360 0.652048 0.666474
# max 3.000000 2.880646 3.000000 2.698668
'''
排列,随机采样
'''
df=DataFrame(np.arange(20).reshape(5,4))
print(df)
#随机排列五个整数
sampler=np.random.permutation(5)
print(sampler)
#将sampler代替索引
print(df.take(sampler))
# 0 1 2 3
# 4 16 17 18 19
# 1 4 5 6 7
# 2 8 9 10 11
# 3 12 13 14 15
# 0 0 1 2 3
#随机获取前三个数
print(np.random.permutation(len(df))[:3])
# [0 1 3]
print(df.take(np.random.permutation(len(df))[:3]))
# 0 1 2 3
# 1 4 5 6 7
# 2 8 9 10 11
# 0 0 1 2 3
'''
哑变量
也叫虚拟变量,引入哑变量的目的是,将不能够定量处理的变量量化,如职业、性别对收入的影响,战争、自然灾害对GDP的影响,
季节对某些产品(如冷饮)销售的影响等等。
这种“量化”通常是通过引入“哑变量”来完成的。根据这些因素的属性类型,构造只取“0”或“1”的人工变量,通常称为哑变量,记为D。
举一个例子,假设变量“职业”的取值分别为:工人、农民、学生、企业职员、其他,5种选项,我们可以增加4个哑变量来代替“职业”这个变量,
分别为D1(1=工人/0=非工人)、D2(1=农民/0=非农民)、D3(1=学生/0=非学生)、D4(1=企业职员/0=非企业职员),
最后一个选项“其他”的信息已经包含在这4个变量中了,所以不需要再增加一个D5(1=其他/0=非其他)了。
这个过程就是引入哑变量的过程,其实在结合分析(conjoint analysis)中,就是利用哑变量来分析各个属性的效用值的。
在线性回归分析中引入哑变量的目的是,可以考察定性因素对因变量的影响,引入哑变量有两种方式:加法方式与乘法方式。
所谓加法方式是指,哑变量作为单独的自变量,有独立的系数,从几何意义上来讲,就是只改变回归直线的截距(constant),不改变斜率(B)
而乘法方式则正好相反,不改变截距,只改变斜率,因为哑变量在回归方程中不是作为一个独立的自变量,而是与其中某一个自变量相乘后作为一个自变量。
当然,也可以同时使用加法和乘法来引入哑变量,即同时改变截距和斜率。
由于哑变量的取值只有0和1,它起到的作用像是一个“开关”的作用,它可以屏蔽掉D=0的case,使之不进入分析,在spss软件中就是filter的作用。
我试验了一下,确实如此。
利用spss软件自带的data:car.sav,分析汽车的功率与100米加速时间的关系,将变量“filter_$”作为哑变量,我们分别run两次线性回归分析,
然后对比这2次的结果,来说明上面的想法。
第一次:将哑变量“filter_$”纳入到分析中,同时利用加法和乘法来引入,将“accel”作为因变量,“horse”、“filter_$”、“filter_$*horse”
作为自变量,进行线性回归分析;
第二次,利用变量“filter_$”进行筛选case,即不分析filter_$=0的case,同样将“accel”作为因变量,而只将“horse”作为自变量;
两次的线性回归结果分别为:
第一次:accel=20.495-0.049*horse-0.007*"filter_$*horse"+0.738*filter_$
第二次:accel=21.234-0.056*horse
当filter_$=1时,第一次计算的公式正好等于第二次机算的公式。
'''
#机器学习的转换方式:将分类变量转换为‘哑变量矩阵’,或者‘指标矩阵’;
df=DataFrame({'key':['b','b','a','c','a','b'],'data1':range(6)})
print(pd.get_dummies(df['key']))
# a b c
# 0 0 1 0
# 1 0 1 0
# 2 1 0 0
# 3 0 0 1
# 4 1 0 0
# 5 0 1 0
#加上前缀,方便与其他数据结合
dummies=pd.get_dummies(df['key'],prefix='key')
df_with_dummy=df[['data1']].join(dummies)
print(df_with_dummy)
# data1 key_a key_b key_c
# 0 0 0 1 0
# 1 1 0 1 0
# 2 2 1 0 0
# 3 3 0 0 1
# 4 4 1 0 0
# 5 5 0 1 0
'''
一个对统计应用有用的秘诀是:结合get_dummies和cut之类的离散化函数
'''
#正态分布是个数值
data=np.random.rand(10)
print(data)
# [0.01472476 0.21786879 0.80685543 0.33888554 0.28585739 0.03260082
# 0.86698275 0.86326211 0.36818782 0.04061498]
#设置面元
bins=[0,0.2,0.4,0.6,0.8,1]
#面元划分
print(pd.cut(data,bins))
# [0.09044921 0.34034557 0.16417927 0.45625488 0.05030981 0.26397673
# 0.93966121 0.17444847 0.19196159 0.48356917]
# [(0.0, 0.2], (0.2, 0.4], (0.0, 0.2], (0.4, 0.6], (0.0, 0.2], (0.2, 0.4], (0.8, 1.0], (0.0, 0.2], (0.0, 0.2], (0.4, 0.6]]
# Categories (5, interval[float64]): [(0.0, 0.2] < (0.2, 0.4] < (0.4, 0.6] < (0.6, 0.8] < (0.8, 1.0]]
# (0.0, 0.2] (0.2, 0.4] (0.4, 0.6] (0.6, 0.8] (0.8, 1.0]
#哑变量
print(pd.get_dummies(pd.cut(data,bins)))
# (0.0, 0.2] (0.2, 0.4] (0.4, 0.6] (0.6, 0.8] (0.8, 1.0]
# 0 1 0 0 0 0
# 1 0 1 0 0 0
# 2 1 0 0 0 0
# 3 0 0 1 0 0
# 4 1 0 0 0 0
# 5 0 1 0 0 0
# 6 0 0 0 0 1
# 7 1 0 0 0 0
# 8 1 0 0 0 0
# 9 0 0 1 0 0
又是美好的周一了,要加油了
每天进步一点点