5.离散化和装箱
连续型数据经常离散化或分散成bins(分箱)来分析。
假设又一组数据,数据代表不同的年龄,把人分到不同的年龄组
import numpy as pd
import pandas as pd
from numpy import nan as NA
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
#把上诉年龄下面分到不同的bins中,19~25, 26~35, 36~60, >60。可以用pandas里的cut:
bins=[18,25,30,60,100]
cats=pd.cut(ages,bins)
print(cats)
#输出:
[(18, 25], (18, 25], (18, 25], (25, 30], (18, 25], ..., (30, 60], (60, 100], (30, 60], (30, 60], (30, 60]]
Length: 12
Categories (4, interval[int64]): [(18, 25] < (25, 30] < (30, 60] < (60, 100]]
#可以看到bins 被cut分为4个部分,每个部分都是范围,然后将ages中的年龄返回表示在bins 中的哪个部分
返回的是一个特殊的Categorical object。我们看到的结果描述了pandas.cut如何得到bins。可以看作是一个string数组用来表示bin的名字,它内部包含了一个categories数组,用来记录不同类别的名字,并伴有表示ages的label
print(cats.codes) #表示ages的label,因为bins 一共又4个部分0-3
print(cats.categories) #返回类别
#输出:
[0 0 0 1 0 0 2 2 3 2 2 2]
IntervalIndex([(18, 25], (25, 30], (30, 60], (60, 100]]
closed='right',
dtype='interval[int64]')
print(pd.value_counts(cats)) #统计cats中每个相同类别的个数,因为cats返回的是灭个年龄的类别
#这里pd.value_counts(cats)是pandas.cut后bin的数量
#输出:
(30, 60] 5
(18, 25] 5
(60, 100] 1
(25, 30] 1
dtype: int64
我们在创建bin的区间时,默认时左开又闭,但是我们可以向cut函数中传入参数right=False,意思是左闭右开。
print(pd.cut(ages,[18,26,31,61,101],right=False))
#输出:
[[18, 26), [18, 26), [18, 26), [26, 31), [18, 26), ..., [31, 61), [61, 101), [31, 61), [31, 61), [31, 61)]
Length: 12
Categories (4, interval[int64]): [[18, 26) < [26, 31) < [31, 61) < [61, 101)]
在默认中bin的类别名称就是一个数字到另外一个数字的范围,我们可以使用一个list或数组来给labels选项来设定bin的名字
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
print(pd.cut(ages,bins,labels=group_names)) #只是将(18,25],(25,30]等换了一个名字而已,bin的范围大小还是不变
#输出:
[Youth, Youth, Youth, YoungAdult, Youth, ..., MiddleAged, Senior, MiddleAged, MiddleAged, MiddleAged]
Length: 12
Categories (4, object): [Youth < YoungAdult < MiddleAged < Senior]
当给一个bins的数量来切分,而不是自己去设定每个bins的范围,那么cut函数会根据传入数据的最大值和最小值来计算等长的bins,就是每个bins的长度范围等长
data=pd.cut(np.random.randn(20),4,precision=2) #np.random.randn(20)产生20个随机数字,然后bin分为4种,然后切分,precision=2表示精确每个bins到小数点后两位
#输出:
[(-1.04, -0.11], (-1.04, -0.11], (-0.11, 0.82], (-1.04, -0.11], (0.82, 1.75], ..., (-1.04, -0.11], (-1.04, -0.11], (-1.98, -1.04], (-1.04, -0.11], (-0.11, 0.82]]
Length: 20
Categories (4, interval[float64]): [(-1.98, -1.04] < (-1.04, -0.11] < (-0.11, 0.82] < (0.82, 1.75]]
近似函数qcut(),它分的bins ,会保证每个bins有相同个数的数据点,因为qcut是按照百分比来切分的
data=np.random.randn(1000)
cats=pd.qcut(data,4)
print(cats)
print(pd.value_counts(cats)) #统计每个bin的数据量,最后可以看出每个bin的数据量都是一样的
#输出:
Length: 1000
Categories (4, interval[float64]): [(-3.06, -0.591] < (-0.591, 0.0336] < (0.0336, 0.687] <
(0.687, 3.55]]
(0.687, 3.55] 250
(0.0336, 0.687] 250
(-0.591, 0.0336] 250
(-3.06, -0.591] 250
dtype: int64
cut和qcut,这些离散函数对于量化和群聚分析很有用!!!
6.检测和过滤异常值
过滤和转换异常值是数组中很重的一个操作,所以这个知识点很重要,谨记!
data=pd.DataFrame(np.random.randn(1000,4))
print(data.describe()) describe函数是查看数据的分布情况 可返回变量和观测的数量、缺失值和唯一值的数目、平均值、分位数等相关信息。我之前有赋过一张表,里面解释了每个的意思,这里mean是平均值,std标准差
#
0 1 2 3
count 1000.000000 1000.000000 1000.000000 1000.000000
mean 0.034130 -0.010546 0.031287 -0.018945
std 1.027747 1.026583 1.034798 0.967755
min -3.315814 -3.168130 -3.458382 -2.902957
25% -0.639957 -0.689596 -0.647237 -0.681589
50% 0.055545 0.015397 0.049480 0.005087
75% 0.695106 0.716642 0.681778 0.647246
max 3.574917 2.545372 2.973921 3.583291
假设我们想找这个data中绝对值大于3的数字
#因为数据过大有1000行,我们就返回data的前5行来寻找
print(data.head())
#输出:
0 1 2 3
0 1.611005 -1.069570 0.141291 -0.952645
1 -0.380136 1.683400 -0.580652 -0.700371
2 -1.142718 -0.735791 -3.064287 -1.216154
3 0.506688 -0.265969 -1.303375 -1.019275
4 -1.118206 1.550753 1.315599 -0.488782
col=data1[2] #取得data中columns为2得那一列得数据
print(col.head())
#输出:
0 0.141291
1 -0.580652
2 -3.064287
3 -1.303375
4 1.315599
print(np.abs(col)>3)
print(col[np.abs(col) > 3]) #np.abs(col)>3 会返回col这个列的布尔类型数据,不满足条件的为False,满足条件的为True
#输出:
995 False
996 False
997 False
998 False
999 False
Name: 2, Length: 1000, dtype: bool #这个只是截取一部分
52 -3.218709
62 3.114901
482 -3.588008
737 3.080875
813 3.057308
Name: 2, dtype: float64
print(data[(np.abs(data) > 3)].head()) #这个表示data数据中得每一行得数字绝对值都必须大于3,显然那是不可能的,所以返回的
#首5行数据缺位缺失值,表明没有这样的值
print(data[(np.abs(data)>3).any(1)]) #表示选取data数据中,每行有一列的数字满足这个条件的
#输出:
0 1 2 3
0 NaN NaN NaN NaN
1 NaN NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN NaN NaN NaN
4 NaN NaN NaN NaN
0 1 2 3
100 -3.072365 -0.078140 -0.201873 1.131444
136 0.220908 -0.783075 3.210207 -0.064182
304 -1.450086 -1.400088 0.296908 3.086599
393 0.954320 3.335903 -0.302396 -0.455293
488 -0.035747 0.749712 -0.824296 -3.323456
519 -0.848282 -3.334016 -0.099327 0.693206
575 -3.493005 1.583037 -0.493140 0.316778
648 0.414687 -3.104181 0.685408 -0.945478
715 0.411987 -0.787592 -3.338853 0.087688
884 3.285694 1.539924 -0.632090 0.613689
975 -3.045808 -0.373709 2.035942 0.262163
np.sign() 函数是根据传入数据的正负号 来得到+1 或 -1,返回一个新的data
print(np.sign(data).head()) #根据data数据中得到-1 或+1
#输出:
0 1 2 3
0 -1.0 -1.0 -1.0 1.0
1 1.0 1.0 1.0 -1.0
2 1.0 1.0 1.0 -1.0
3 1.0 -1.0 -1.0 -1.0
4 -1.0 1.0 -1.0 -1.0
data[np.abs(data)>3]=np.sign(data)*3 # 将data中数据大于3的数字赋值为3,或则-3
print(data[(np.abs(data)>=3).any(1)])
#输出:
0 1 2 3
38 1.283115 1.094888 -0.941362 -3.000000
72 -0.231678 3.000000 0.402873 -0.872957
356 0.133103 1.337680 3.000000 1.996030
376 -3.000000 0.877116 -1.267313 -0.644417
388 -0.908056 0.393500 3.000000 -0.787527
409 -1.227639 -1.330704 0.404324 -3.000000
421 0.075262 -0.513744 3.000000 -0.140479
582 -3.000000 0.130571 -1.276300 -0.162316
612 3.000000 0.602845 -1.699048 1.446110
840 -0.328060 -0.849822 -3.000000 -1.000604
885 -0.532064 -0.651618 -1.639361 -3.000000
891 -0.877902 -1.451622 -1.658073 -3.000000
892 -2.354666 -0.331953 1.283252 -3.000000
print(data.describe()) #显示数据中各种信息
#输出:
0 1 2 3
count 1000.000000 1000.000000 1000.000000 1000.000000
mean -0.060311 0.018493 0.040830 0.008197
std 1.038350 1.008272 0.984851 0.983521
min -3.000000 -3.000000 -3.000000 -3.000000
25% -0.721603 -0.650585 -0.602932 -0.672454
50% -0.066891 0.020827 0.011951 0.077265
75% 0.653727 0.712820 0.719602 0.698649
max 3.000000 3.000000 3.000000 2.669392
可以看到数据中最大值max的变化
7.排列和随机采样
排列(随机排列-->顺序是随机)一个Series 或DataFrame 中的row,用numpy.random.permutation函数很容易做到。可以设定好需要的axis,来表示想排列多少row 。它会产生一个数组表示新的顺序
data=pd.DataFrame(np.arange(5*4).reshape(5,4)) #arange(5*4) 产生数字20个,从0到19 生成为二维数组,为5*4
#输出:
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
4 16 17 18 19
s=np.random.permutation(5)
print(s)
#这个数组能被用在基于iloc上的indexing(根据索引寻找)或take函数(根据索引返回索引的表)
print(data.take(s))
#输出:
[1 4 3 0 2] #产生一个数组表示新的顺序
0 1 2 3
1 4 5 6 7
4 16 17 18 19
3 12 13 14 15
0 0 1 2 3
2 8 9 10 11
为了选中一个data中一个新的随机的子集,而且没有替代功能,返回一个新的Series 或DataFrame ,我们可以使用sample()
print(data.sample(n=3)) #产生一个随机的子集,row大小为3
#输出:
0 1 2 3
4 16 17 18 19
0 0 1 2 3
1 4 5 6 7
如果想要产生的样本具有替代功能(即允许其中的数据有重复),我们可以在sample()中传入参数repalce=True
df=pd.Series([2,4,8,9,5])
print(df.sample(n=10,replace=True)) #产生一个随机子集,row大小为10
#输出:
4 5
4 5
3 9
0 2
1 4
3 9
3 9
4 5
1 4
0 2
dtype: int64
8.计算指示器/虚拟变量 Computing Indicator/Dummy Variables
虚拟变量,又称虚设变量、名义变量或哑变量,用以反映质的属性的一个人工变量,是量化了的自变量,通常取值为0或1
如果DataFrame中的一列有k个不同的值,我们可以用一个矩阵或DataFrame用k列来表示,1或0。(就是相当于返回一个新的DataFrame,列索引为一列k个不同的值,然后1或0表明一列的每行拥有的值是什么,就是在每列下面1为 有这个值,0表明没有这个值)
那么这些我们可以使用pandas的get_dummies函数
df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
'data1': range(6)})
print(df)
print(pd.get_dummies(df['key'])) #传入索引列为key的数据
#输出:
data1 key
0 0 b
1 1 b
2 2 a
3 3 c
4 4 a
5 5 b
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
#这里的b为1,因为在df中 Key列第一行的数据就是为b,这样依次类推
dummies=pd.get_dummies(df['key'],prefix='key') #我们可以使用get_dummies()中的参数prefix来给每一列加上一个字首(prefix)
print(dummies)
#输出:
key1_a key1_b key1_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
df_dummies=df[['data1']].join(dummies) #df[['data1']](注意这里是两个[])加上dummies 组合成一个新的DataFrame结构
print(df_dummies)
#输出:
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
因为自己看得那个jupyter,有些知识点涉及到了数据集,暂时还没有下载到那个数据集,所以后面的无法学习,等有了再学习。