day06

01-合并数据
import pandas as pd

"""
import numpy as np
numpy 合并数组
np.hstack() # 水平合并
np.vstack() # 垂直合并
np.concatenate() # 行的方向 axis = 0
np.concatenate() #  列的方向 axis = 1
""" 

# # 获取df数据
# df1 = pd.read_excel('./直接拼接数据.xlsx', sheetname=0)
# df2 = pd.read_excel('./直接拼接数据.xlsx', sheetname=1)
# print('df1:\n', df1)
# print('df2:\n', df2)
# print('*' * 100)

# 直接拼接 ---pd.concat   四种
# axis=0,join='outer' 行的方向上外连接
# 行上直接拼接,列的方向上求并集,如果没有值的地方用NaN补齐
# res = pd.concat((df1, df2), axis=0, join='outer')
# print('res:\n', res)
# axis=0,join = 'inner' ,行的方向上内连接
# 行上直接拼接,列的方向上求交集
# res = pd.concat((df1, df2), axis=0, join='inner')
# print('res:\n', res)

# axis=1,join='outer' 列的方向上外连接
# 列上直接拼接,行的方向上求并集,如果没有值的地方用NaN来补齐
# res = pd.concat((df1, df2), axis=1, join='outer')
# print('res:\n', res)
# axis=1, join='inner' ,列的方向上内连接
# 列上直接拼接,行的方向上求交集
# res = pd.concat((df1, df2), axis=1, join='inner')
# print('res:\n', res)


# 主键拼接方式     八种
# 获取df数据
# left = pd.read_excel('./主键拼接数据.xlsx', sheetname=0)
# right = pd.read_excel('./主键拼接数据.xlsx', sheetname=1)
# print('left:\n', left)
# print('right:\n', right)
# print('*' * 100)

# how='outer', on='key' 按照key列进行拼接,找的key 的并集
# res = pd.merge(left=left, right=right, how='outer', on='key')
# print('res:\n', res)

#  how='inner', on='key'按照key列进行拼接,找的key 的交集
# res = pd.merge(left=left, right=right, how='inner', on='key')
# print('res:\n', res)


# how='left', on='key' 按照左表中的key进行拼接,右表配合左表,如果右表没有的数据,用NaN来补齐
# res = pd.merge(left=left, right=right, how='left', on='key')
# print('res:\n', res)

#  how='right', on='key' 按照右表中的key进行拼接,左表配合右表,如果左表没有数据,用NaN来补齐
# res = pd.merge(left=left, right=right, how='right', on='key')
# print('res:\n', res)

# 当左右两个df中的列里面的值大部分相同,其列名不相同的场景
left = pd.read_excel('./主键拼接数据.xlsx', sheetname=2)
right = pd.read_excel('./主键拼接数据.xlsx', sheetname=3)
print('left:\n', left)
print('right:\n', right)
print('*' * 100)

# 主键拼接
# how='outer', left_on='kk', right_on='gg'
# 用左表中kk 与右表中的gg列的值进行拼接,并求取的是并集,如果没有的数据用NaN类补齐
# res = pd.merge(left=left, right=right, how='outer', left_on='kk', right_on='gg')
# print('res:\n', res)

#  how='inner', left_on='kk', right_on='gg'
# 用左表中kk 与右表中的gg列的值进行拼接,并求取的是交集
# res = pd.merge(left=left, right=right, how='inner', left_on='kk', right_on='gg')
# print('res:\n', res)

#  how='left', left_on='kk', right_on='gg'
# 用左表中kk 与右表中的gg列的值进行拼接,用右表来配合左表,如果右表中没有的值用NaN补齐
# res = pd.merge(left=left, right=right, how='left', left_on='kk', right_on='gg')
# print('res:\n', res)

#  how='right', left_on='kk', right_on='gg'
# 用左表中kk 与右表中的gg列的值进行拼接,用左表来配合右表,如果左表中没有的值用NaN来补齐
# res = pd.merge(left=left, right=right, how='right', left_on='kk', right_on='gg')
# print('res:\n', res)

02-数据合并案例
import pandas as pd
import numpy as np
        
# 将detail 与info 与users拼接成一个大的数据集

# 加载detail
detail_0 = pd.read_excel("./meal_order_detail.xlsx", sheetname=0)
detail_1 = pd.read_excel("./meal_order_detail.xlsx", sheetname=1)
detail_2 = pd.read_excel("./meal_order_detail.xlsx", sheetname=2)
print('detail_0:\n', detail_0.shape)
print('detail_0:\n', detail_0.columns)
print('*' * 100)
print('detail_1:\n', detail_1.shape)
print('detail_1:\n', detail_1.columns)
print('*' * 100)
print('detail_2:\n', detail_2.shape)
print('detail_2:\n', detail_2.columns)
print('*' * 100)

# 将detail 拼接成一个完整的数据集
# 直接拼接 
detail = pd.concat((detail_0, detail_1, detail_2), axis=0, join='inner')
print('detail:\n', detail.shape)
print('detail:\n', detail.columns)
print('*' * 100)

# 加载user 与info
info = pd.read_csv('./meal_order_info.csv', encoding='ansi')
print('info:\n', info.shape)
print('info:\n', info.columns)
print('*' * 100)
users = pd.read_excel('./users.xlsx')
print('users:\n', users.shape)
print('users:\n', users.columns)
print('*' * 100)

# 将user 与 info 进行主键拼接
res = pd.merge(left=users, right=info, how='inner', left_on='ACCOUNT', right_on='name')
print('res:\n', res.shape)
print('res:\n', res.columns)
print('*' * 100)

# 将detail 与 res 进行主键拼接
data = pd.merge(left=detail, right=res, how='inner', left_on='order_id', right_on='info_id')
print('data:\n', data.shape)
print('data:\n', data.columns)
print('*' * 100)

# 判断 emp_id_x  与 emp_id_y  是否都是一样的?
# a = np.all(data.loc[:,"emp_id_x"] == data.loc[:,"emp_id_y"])
# print('a:\n',a)

# 删除掉  emp_id_y info_id ACCOUNT
data.drop(labels=['emp_id_y', 'info_id', 'ACCOUNT'], axis=1, inplace=True)
print('最终的data:\n', data.shape)
print('最终的data:\n', data.columns)
print('*' * 100)

drop_list = []
# 剔除全部为空的列
for column in data.columns:
    # 判断为空的列
    res = data.loc[:, column].count()
    if res == 0:
        drop_list.append(column)

# 删除全部为空的列
data.drop(labels=drop_list, axis=1, inplace=True)
print('删除全部为缺失的列之后的结果:\n', data.shape)
print('删除全部为缺失的列之后的结果:\n', data.columns)
print('*' * 100)

drop_list = []
# 剔除 整列值都是一样的列
for column in data.columns:
    res = data.drop_duplicates(subset=column, inplace=False)
    if res.shape[0] == 1:
        drop_list.append(column)
print('*' * 100)
# 删除 值全部一样的列
data.drop(labels=drop_list, axis=1, inplace=True)
print('删除值全部一样的列之后的结果:\n', data.shape)
print('删除值全部一样的列之后的结果:\n', data.columns)
print('*' * 100)

03-缺失值的检测和处理
import pandas as pd
import numpy as np

# 加载数据
data = pd.read_excel("./qs.xlsx")
print('data:\n', data)
print('data的列索引:\n', data.columns)

# 检测缺失值
#  isnull + sum
res_null = pd.isnull(data).sum()
print('res_null:\n', res_null)
print('*' * 100)

# notnull + sum
# res_null = pd.notnull(data).sum()
# print('res_null:\n',res_null)

# 处理缺失值
# 1、删除法 ---简单粗暴,易懂易操作,不能随意使用,如果随意使用,可能会造成数据的大量丢失
# 只有整行或者整列 大部分为缺失值或者全部为缺失值,才能进行使用
# axis=0, ---行, axis = 1 列
# how='any' ---只要有缺失值,就删除整列或者整行
# inplace=False # 不对df产生影响, inplace=True--直接对df产生影响
# data.dropna(axis=0, how='any', inplace=True)
# data.dropna(axis=1, how='any', inplace=True)
# how = 'all' ----只有整行、或者整列 全部为缺失值,才进行删除
# data.dropna(axis=1, how='all', inplace=True)
# print('删除之后的结果:\n', data)

# 2、填充法
# 可能造成 数据分布规律 发生变化,可能会对数据分析结果产生影响
# 如果填充不会对数据分布产生影响,或者不会对数据分析结果产生影响
# fillna
# 数值型数据---可以使用均值、中位数、众数来进行填充
# 非数值型数据--可以使用众数来进行填充
# 都可以使用数据的上下邻居来进行填充
# 使用众数 来填充商品ID这一列
# mode = data['商品ID'].mode()[0]
# print('mode:\n', mode)
# data['商品ID'].fillna(value=mode, inplace=True)
#
# # 使用上下邻居来填充 类别ID
# # method='pad' 或者'ffill' ---使用上邻居填充
# # method='bfill' 或者 'backfill' ---使用下邻居填充
# data.loc[:, "类别ID"].fillna(method='backfill', inplace=True)
#
#
# # 使用上邻居来填充门店编号
# data.loc[:, '门店编号'].fillna(method='pad', inplace=True)
#
# print('填充之后的结果:\n', data)
# 3、插值法
# 线性插值 ---拟合线性关系进行插值
# 多项式插值 ---拟合多项式关系进行插值
# -----常用多项式插值:拉格朗日多项式插值、牛顿多项式插值
# 样条插值 ---拟合样条关系进行插值
# from scipy.interpolate import spline  # 样条插值模块
# from scipy.interpolate import lagrange  # 拉格朗日多项式插值
# from scipy.interpolate import interp1d  # 线性插值
#
# x = np.array([1, 2, 3, 4, 5, 8, 9])
# y = np.array([3, 5, 7, 9, 11, 17, 19])  # y = 2x + 1
# z = np.array([2, 8, 18, 32, 50, 128, 162])  # z = 2 * x^2
#
# # 线性插值 ---拟合直线关系
# liner_1 = interp1d(x=x, y=y, kind='linear')  # [ 13.  15.]
# # kind = 'cubic'  # 理解为拟合曲线
# liner_2 = interp1d(x=x, y=z, kind='linear')  # [  76.  102.]
#
# print(liner_1([6, 7]))
# print(liner_2([6, 7]))
# print('*' * 100)
#
# # 拉格朗日多项式插值 --拟合拉格朗日多项式
# la1 = lagrange(x=x, w=y)  # [ 13.  15.]
# la2 = lagrange(x=x, w=z)  # [ 72.  98.]
# print(la1([6, 7]))
# print(la2([6, 7]))
# print('*' * 100)
#
# # 样条插值 --拟合样条
# print(spline(xk=x, yk=y, xnew=[6, 7]))  # [ 13.  15.]
# print(spline(xk=x, yk=z, xnew=[6, 7]))  # [ 72.  98.]

# 线性插值 对 线性数据表现较好,对非线性数据标表现不好
# 拉格朗日插值、样条插值 对线性数据表现较好,对非线性数据也表现较好 ---推荐

# 对于 * ? " " : 等特殊字符的缺失值??
# 1、将特殊字符替换为np.nan
data.replace("*", np.nan, inplace=True)
print('data:\n',data)
# 2、再进行删除、填充、插值

# np.nan 类型???----<class 'float'>
# print(type(np.nan))
04-异常值剔除
import pandas as pd


# 3sigma原则 ----99.73% [u-3a,u+3a]之间,认为超出这个范围的就是异常值
def three_sigma(data):
    """
    3sigma原则剔除异常值
    :param data: series类型
    :return: bool_index
    """
    # 上限
    up = data.mean() + 3 * data.std()
    # 下限
    low = data.mean() - 3 * data.std()

    #
    bool_index_1 = low <= data
    bool_index_2 = data <= up

    # 同时满足 小于 上限, 大于 下限
    bool_index = bool_index_1 & bool_index_2

    return bool_index


# 箱线图分析
# up = qu + 1.5iqr # (1,3)---1.5最常用的
# low = ql - 1.5iqr
# (low,up) ---正常的值,如果超过这个范围,认为是异常的
def box_analysis(data):
    """
    箱线图分析法提出异常值
    :param data: series
    :return: bool_index
    """
    # 确定上四分位数
    qu = data.quantile(q=0.75)
    # 确定下四分位数
    ql = data.quantile(q=0.25)
    # 确定分位数间距
    iqr = qu - ql
    # 确定上限
    up = qu + 1.5 * iqr
    # 确定下限
    low = ql - 1.5 * iqr

    #
    bool_index = (low <= data) & (data <= up)

    return bool_index


# 加载数据
data = pd.read_excel("./meal_order_detail.xlsx")
print('data:\n', data)
print('data 的列索引:\n', data.columns)
print('*' * 100)
# 验证
# 使用amounts 列进行验证 3sigma原则
# bool_index = three_sigma(data.loc[:, 'amounts'])
# 使用amounts 列进行验证 箱线图分析法
bool_index = box_analysis(data.loc[:, 'amounts'])
# 选出在正常范围内的值
data = data.loc[bool_index, :]
print('data:\n', data)

05-数据标准化处理
import pandas as pd
import numpy as np
# 标准化目的:去除数据量级的影响
# 离差标准化
# 将数据转化到[0,1]
# x = (x - min) / max -min
def min_max_sca(data):
    """
    离差标准化进行标准化数据
    :param data: df 或者series
    :return: 标准化之后的数据
    """
    data = (data - data.min()) / (data.max() - data.min())
    return data
# 标准差标准化
# 将数据转化为符合标准正态分布的数据---u=0,a=1
# x = (x - mean) / std
def stand_sca(data):
    """
    标准差标准化数据
    :param data: df或者series
    :return: 标准化之后的数据
    """
    data = (data - data.mean()) / data.std()
    return data
# 小数定标标准化
# 通过移动小数位数来进行标准化
#  x = x / 10^k
# k ---> log10(|x|.max()) --->向上取整
def desc_sca(data):
    """
    小数定标标准化
    :param data: df 或者series
    :return: 标准化之后的数据
    """
    # np.floor() --->向下取整
    data = data / (10 ** int(np.ceil(np.log10(data.abs().max()))))
    return data
# 验证
data = pd.read_excel("./meal_order_detail.xlsx")
print('data:\n', data)
print('data 的列索引:\n', data.columns)
print('*' * 100)
# 将 amounts 进行标准化
# data.loc[:, 'amounts'] = min_max_sca(data.loc[:, 'amounts'])
# data.loc[:, 'amounts'] = stand_sca(data.loc[:, 'amounts'])
data.loc[:, 'amounts'] = desc_sca(data.loc[:, 'amounts'])
print('标准化之后的结果:\n', data.loc[:, 'amounts'])
# print('均值:',data.loc[:, 'amounts'].mean())
# print('标准差:',data.loc[:, 'amounts'].std())
# 标准化之后的数据----没有真实具体解释意义,可以用于代替原来的数据参与计算
day06day06 return_min 发布了128 篇原创文章 · 获赞 24 · 访问量 4129 私信 关注
上一篇:算法基础二:渐增型算法---序列的划分


下一篇:day06 【类与对象、封装、构造方法】