'''
@author yokan
@date 2018/5/17
'''
import numpy as np
import pandas as pd
from datetime import datetime
from sklearn import preprocessing
from sklearn.feature_extraction.text import CountVectorizer #从sklearn导入词袋相关库
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
from sklearn.datasets import load_iris
from sklearn.datasets import load_boston
from sklearn.feature_selection import RFE
from sklearn.linear_model import LinearRegression
from sklearn.svm import LinearSVC
from sklearn.feature_selection import SelectFromModel
from scipy.stats import pearsonr
#统计值
series = pd.Series(np.random.randn(666)) #得到一个666个随机的浮点数
# print(series.describe(percentiles = [0.25,0.5,0.75,0.99])) #得到一些统计相关的值,percentiles为分位数,std是方差,mean是均值
#离散化
# r_mat = np.array([[1.0,2.0,3],[4.0,5.0,6.0],[7.0,8.0,9.0]])
# scaler = preprocessing.MinMaxScaler()
# scale_mat = scaler.fit_transform(r_mat)
# print(scale_mat)
arr = (np.random.randn(6666)) #得到一个6666个随机的浮点数
# print(arr)
res = pd.cut(arr,4) #把数值分成4份,得到一个概率区间,因为在6666个近似连续分布的数里面
# print(res) #求单个值是没意义的,概率太小,且没代表性,而分成4个值就变的有意义了
#特征处理
#下面生成的是日期特征函数,后面方便做特征分析
#因为一般数据给的都是字符串,所以需要先转换成datetime才方便取week之类的时期信息
day_of_week = lambda x:datetime.strptime(x,"%Y-%m-%d %H:%M:%S").weekday()
month = lambda x:datetime.strptime(x,"%Y-%m-%d %H:%M:%S").month()
week_number = lambda x:datetime.strptime(x,"%Y-%m-%d %H:%M:%S").strftime("%V") #这个%V比较特殊是转换成这年的第几周一年有365天/7大概是52.xxx周,不足一周按一周算,所以是53周
seasons = [0,0,1,1,1,2,2,2,3,3,3,0]
season = lambda x:seasons[datetime.strptime(x,"%Y-%m-%d %H:%M:%S").month - 1] #区分季节,0代表冬季,1代表春季,2代表夏季3代表秋季,得到的month是一个[1:12]的数而数组对应下标是从0开始故而-1
times = [0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,4,4,4,4,5,5,5,0] #比如对于一个家庭主妇来说,24-6睡觉6-9点准备早餐,类似这样的把一个连续的24个数据离散成6个数,从而找出相对应的特征,
time_quantum = lambda x:times[datetime.strptime(x,"%Y-%m-%d %H:%M:%S").hour - 1] #比如6-9点是做饭时间就可以分析出她需要买早餐的材料或者看一系列早餐的文章,就可以对手机进行推送相关信息
#特征处理->词袋
#emmm,词袋可以理解为对字符串的离散化,用个计算机术语就叫做枚举出来,把原来的类别化成1,2,3,4之类的连续数字
#sklearn的CountVectorizer就能完美解决这个问题,关键词的频率和分类,都能处理
vec = CountVectorizer(min_df=1) #min_df是最小关键词,当我设置为2的时候you see Don't这些只出现过一次的词就不会作为关键词处理了
words = ['this is my car','this is my wifi','where is your is wifi?','is there,Do you see?']
x = vec.fit_transform(words) #进行关键词筛选
b_vec = CountVectorizer(ngram_range=(1,2),token_pattern=r"\b\w+\b",min_df=1) #token_pattern是一个匹配的正则表达式
analyze = b_vec.build_analyzer() #创建分析对象
#2333不好意思我就是如此的不要碧莲,这段的意思建立一个语言模型,它的结果就是后面那段,返回的是通过正则表达式筛选出来token_pattern=r"\b\w+\b"符合ngram_range=(1,2)1-2个词的组合
# print(analyze('yokan is very handsome!')) #(['yokan','is','very','handsome','yokan is','is very','very handsome'])
#先说想实现的效果,比如词is在words四个词组里面全部都出现过就拿到[1,1,1,1],没拿到就是[0,0,0,0]比如第二个拿到第三个拿到其它没有就取[0,1,1,0]
x1 = b_vec.fit_transform(words).toarray() #生成一个4*24阶的矩阵,4是4个数字,里面的列向量,从上到下代表该词汇在这句话里面出现的次数
fIndex = b_vec.vocabulary_.get("where is") #上面的数字1个和连续两个总共有24种组合方式,对应的值是[0-23],查出来的就是对应的列
# print(x1[:,fIndex]) #把对应的列取出来,得到的值就是这个字符在4个语句里面出现的次数
#特征处理->特征选择常见库和API
#特征选择是进行特征的筛选,去掉一些微弱的值,做个比喻y = 0.00001x1 + 140*x2 这个方程,x1在这个方程起到的作用微乎其微,是不是就去掉,还能降一维
#这个依赖库为scipy下的pearsonr,这个库效率很高,并且效果也很显著,但因为它不考虑特征之间的关联性,可能会剔除掉有用的特征
l = 666
x2 = np.random.normal(0,1,l) #生成666个服从正态分布的随机数,期望是0方差是1,这就意味着这是个标准正态分布
# print(pearsonr(x,x + np.random.normal(0,1,l))) #这pearsonr就是判断两个的相关系数,输出来一看就知道上面那个相关性要大的多
# print(pearsonr(x,x + np.random.normal(0,10,l))) #因为下面这个加的值比上面要大
#sklearn的selectKBest
iris = load_iris() #模拟一个数据集
x3,y = iris.data,iris.target #拆分成两个,得到的结果有四个特征,然后有150个不同的值
x_n = SelectKBest(chi2,k = 2).fit_transform(x3,y) #k= 2代表观察之后把相关性最高的两个返还出来,得到的结果是150*2的矩阵
# print(x_n)
#sklearn的rfe,
boston = load_boston() #和iris类似,也是生成一个数据集,然后拆分方式有一丝不同
x4,y1,names = boston["data"],boston["target"],boston["feature_names"] #拆分成x,y,names x为特征数据,y为结果,names为名称
lr = LinearRegression() #初始化一个逻辑回归对象
rfe = RFE(lr,n_features_to_select=1) #初始化一个RFE,可以说是一个逻辑回归的处理对象,传入逻辑回归对象,n_features_to_select是特征选择数目,我暂时也没搞太懂
rfe.fit(x4,y1) #这是个程序处理函数,写好了初始值之后开始运行
#将得到的结果和names一起打包成列表
# print(sorted(zip(map(lambda x:round(x,4),rfe.ranking_),names)))
# sklearn的SelectFromModel
#懒得注释了,反正又是一种特征处理的api
lsvc = LinearSVC(C=0.01,penalty="l1",dual=False).fit(x3,y)
model = SelectFromModel(lsvc,prefit=True)
x_n = model.transform(x3)
print(x_n)