2021-04-05

                         **根据逻辑回归填补缺失值**

在这里插入图片描述
数据预处理整体思路:
观察数据可知,这个数据集是类似于一个行业中某一集团的商品销售数据,缺失数据为采购单价和销售单价,销售数量和销售金额有异常值,我们首先要对缺失数据进行补充。
先看看采购单价,根据生活经验可知,一个商品的采购单价首先和商品本身相关性最大,其次和采购该商品的时间节点有关,最后是和采购该商品的主体相关。观察数据可知,与此相关的feature有交易日期,门店编号,商品编号,商品处编号,商品部门编号,其中交易的年月信息已经包含在交易日期内了,所以予以舍弃,收银台信息影响不大,在无法得知更多信息的前提下,我们认为其并不影响采购单价和销售单价的决策,所以也舍弃掉。
再对这些特征进行统计可知。
Name: 交易日期, Length: 310, dtype: int64
Name: 商品编号, Length: 6359, dtype: int64
Name: 销售数量, Length: 521, dtype: int64
Name: 采购单价, Length: 4170, dtype: int64
Name: 销售单价, Length: 1227, dtype: int64
而整体数据有近130万条, 所以这些特征的类别相对数据量来说并不多,因此我们猜想通过这些特征的排列组合是可以确定采购单价的,我们可以对这些特征进行一个logistic回归,根据前面的这些特征去确定采购单价的类别。
填补完采购单价后,再说下销售单价,销售环节位于采购环节之后,不仅和上述特征相关,同时还和采购单价、销售数量相关。但销售数量存在错误,且销售数量的变动不大,因此在无法得知更多信息的前提下,我们决定在对销售单价进行logistic时舍弃销售数量这个特征,并认为销售数量除了符号错误之外,其他错误都可以忽略。
在填补完销售单价和纠正销售数量后,再根据销售金额=销售数量*销售单价 去纠正销售金额。
由于数据量过大,所以这里先拿部分数据做演示。
完整代码在后面

1、dummy变量处理
这里先说下回归模型的大致形式,先对各个变量进行一个简单的类型统计,看看各个变量大致有多少种类型。

import pandas as pd
data = pd.read_csv("sales2019.csv" ,encoding='gbk')
a=['交易日期', '门店编号', '收银台编号', '商品编号', '交易日期_年份', '交易日期_月份', '商品处编号',
       '商品部门编号', '销售数量', '销售金额', '采购单价', '销售单价']
for each in a:
  print(data[each].value_counts())

Name: 交易日期, Length: 310, dtype: int64
Name: 商品编号, Length: 6359, dtype: int64
Name: 销售数量, Length: 521, dtype: int64
Name: 采购单价, Length: 4170, dtype: int64
Name: 销售单价, Length: 1227, dtype: int64
可以看出,相对于130万的数据量,这些变量的种类数并不多,因此我们可以用一个分类模型来对空缺的数据进行预测。
比如,交易日期有310种,就可以形成310个交易日期有关的哑变量,取值为0,1;其他类似处理。
然后找出与空缺值部分最相似的那个数据,代入进去,比如
在这里插入图片描述
这两个数据完全一样,如果其中一个空缺,就可以用另一个数据直接代入,但如果找不到一模一样的,就找到一个最相似的代入。

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
#data1是原始数据集
data1 = pd.read_csv("sales2019.csv" ,encoding='gbk')
data2 = data1
dummy_fields = ['交易日期','门店编号','收银台编号','商品编号','商品处编号','商品部门编号']
for each in dummy_fields:
  dummies = pd.get_dummies(data2[each],drop_first=False,prefix=each)
  #这里挨个转换独热编码,转换完了一个就粘贴一个
  data2 = pd.concat([dummies,data2],axis=1)
#data2.columns

在这里插入图片描述
粘贴好之后的变量,还需要去掉之前的变量(这里只是以少量数据做了一个示例)。

data2 = data2.drop(fiels_to_drop,axis=1)#去掉旧值后的dummy数据集,
data3 = data2.dropna(axis=0,how='any')#去掉空值行的dummy数据集

在这里插入图片描述
到这里,dummy变量就处理完成并且删除了空值行,方便接下来进行logitisic回归。
2.逻辑回归(采购单价)

features = data3.loc[:, '商品部门编号_12':'交易日期_2019/10/25 0:00']
X = features.values
y = data3['采购单价'].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression()
logreg.fit(X_train,y_train.astype('int'))
print("logistic test score: {:.2f}".format(logreg.score(X_test, y_test.astype('int'))))
#数据量为3万左右时,跑出的分数在0.8左右
a = data2[data2.isnull().T.any()].index
b =logreg.predict((data2.loc[data2[data2.isnull().T.any()].index,'商品部门编号_12':'交易日期_2019/10/25 0:00']).values)
data1.at[a,'采购单价']= b#dummy转换前的数据集(已填补采购单价)
#print(data1)#填补好的数据集

3、逻辑回归(销售单价)

data2.at[a,'采购单价'] = b#去掉旧值且dummy转换后的数据集(已填补采购单价),销售单价依旧为空
data3 = data2.dropna(axis=0,how='any')#去掉空值行的dummy数据集
features1 = data3.loc[:, '商品部门编号_12':'采购单价']
X1 = features1.values
y1 = data3['销售单价'].values
X_train1, X_test1, y_train1, y_test1 = train_test_split(X1, y1, test_size=0.2, random_state=1)
from sklearn.linear_model import LogisticRegression
logreg1 = LogisticRegression()
logreg1.fit(X_train1,y_train1.astype('int'))
print("logistic test score: {:.2f}".format(logreg1.score(X_test1, y_test1.astype('int'))))
#数据量为3万左右时,跑出的分数大致在0.7左右。
a = data2[data2.isnull().T.any()].index#从未删除空值的数据集里找出index,不能从data3找,因为删除空值行后,结构已经变了。
b =logreg1.predict((data2.loc[data2[data2.isnull().T.any()].index,'商品部门编号_12':'采购单价']).values)
data1.at[a,'销售单价'] = b
print(data1)

销售单价的回归与采购单价的思路一致,只是自变量中多了一个采购单价。

4、销售数量和销售金额的处理
直接对销售数量取绝对值,然后销售金额=销售数量*销售单价。
data1[‘销售数量’] = abs(data1[‘销售数量’])
data1[‘销售金额’] = data1[‘销售数量’]*data1[‘销售单价’]
5、完整代码

#数据集说明
#data1是原始数据集,data2是去掉“交易日期”等旧变量后的dummy数据集
#data3是去掉空值后的dummy数据集,到这里为止是为了进行采购单价的回归
#最后得到的data1是处理完成的数据集
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
#dummy变量处理
data1 = pd.read_csv("sales2019.csv" ,encoding='gbk')
data2 = data1
dummy_fields = ['交易日期','门店编号','收银台编号','商品编号','商品处编号','商品部门编号']
for each in dummy_fields:
  dummies = pd.get_dummies(data2[each],drop_first=False,prefix=each)
  #这里挨个转换独热编码,转换完了一个就粘贴一个
  data2 = pd.concat([dummies,data2],axis=1)
fiels_to_drop = ['交易日期','门店编号','收银台编号','商品编号','商品处编号','商品部门编号']
data2 = data2.drop(fiels_to_drop,axis=1)#去掉旧值后的dummy数据集,
data3 = data2.dropna(axis=0,how='any')#去掉空值行的dummy数据集
#采购单价回归
features = data3.loc[:, '商品部门编号_12':'交易日期_2019/10/25 0:00']
X = features.values
y = data3['采购单价'].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression()
logreg.fit(X_train,y_train.astype('int'))
print("logistic test score: {:.2f}".format(logreg.score(X_test, y_test.astype('int'))))
#数据量为3万左右时,跑出的分数在0.8左右
a = data2[data2.isnull().T.any()].index
b =logreg.predict((data2.loc[data2[data2.isnull().T.any()].index,'商品部门编号_12':'交易日期_2019/10/25 0:00']).values)
data1.at[a,'采购单价']= b#dummy转换前的数据集(已填补采购单价)
#销售单价的回归
data2.at[a,'采购单价'] = b#去掉旧值且dummy转换后的数据集(已填补采购单价),销售单价依旧为空
data3 = data2.dropna(axis=0,how='any')#去掉空值行的dummy数据集
features1 = data3.loc[:, '商品部门编号_12':'采购单价']
#这里要注意一点,采购单价并没有进行dummy处理,是一个连续型的数值变量。
X1 = features1.values
y1 = data3['销售单价'].values
X_train1, X_test1, y_train1, y_test1 = train_test_split(X1, y1, test_size=0.2, random_state=1)
from sklearn.linear_model import LogisticRegression
logreg1 = LogisticRegression()
logreg1.fit(X_train1,y_train1.astype('int'))
print("logistic test score: {:.2f}".format(logreg1.score(X_test1, y_test1.astype('int'))))
#数据量为3万左右时,跑出的分数大致在0.7左右。
a = data2[data2.isnull().T.any()].index#从未删除空值的数据集里找出index,不能从data3找,因为删除空值行后,结构已经变了。
b =logreg1.predict((data2.loc[data2[data2.isnull().T.any()].index,'商品部门编号_12':'采购单价']).values)
data1.at[a,'销售单价'] = b
#data1
#销售数量和销售金额
data1['销售数量'] = abs(data1['销售数量'])
data1['销售金额'] = data1['销售数量']*data1['销售单价']
#data1
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值