EDA(Exploratory Data Analysis)探索性数据分析

news2025/1/10 22:35:57

EDA(Exploratory Data Analysis)中文名称为探索性数据分析,是为了在特征工程或模型开发之前对数据有个基本的了解。数据类型通常分为两类:连续类型和离散类型,特征类型不同,我们探索的内容也不同。

1. 特征类型

1.1 连续型特征

定义:取值为数值类型且数值之间的大小具有实际含义。例如:收入。对于连续型变量,需要进行EDA的内容包括:

  • 缺失值
  • 均值
  • 方差
  • 标准差
  • 最大值
  • 最小值
  • 中位数
  • 众数
  • 四分位数
  • 偏度
  • 最大取值类别对应的样本数

1.2 离散型特征

定义:不具有数学意义的特征。如:性别。对于离散型变量,需要进行EDA的内容包括:

  • 缺失值
  • 众数
  • 取值个数
  • 最大取值类别对应的样本数
  • 每个取值对应的样本数

2. EDA目的

​ 通过EDA,需要达到以下几个目的:

​ (1)可以有效发现变量类型、分布趋势、缺失值、异常值等。

​ (2)缺失值处理:(i)删除缺失值较多的列,通常缺失超过50%的列需要删除;(ii)缺失值填充。对于离散特征,通常将NAN单独作为一个类别;对于连续特征,通常使用均值、中值、0或机器学习算法进行填充。具体填充方法因业务的不同而不同。

​ (3)异常值处理(主要针对连续特征)。如:Winsorizer方法处理。

​ (4)类别合并(主要针对离散特征)。如果某个取值对应的样本个数太少,就需要将该取值与其他值合并。因为样本过少会使数据的稳定性变差,且不具有统计意义,可能导致结论错误。由于展示空间有限,通常选择取值个数最少或最多的多个取值进行展示。

​ (5)删除取值单一的列。

​ (6)删除最大类别取值数量占比超过阈值的列。

3.实验

3.1 统计变量类型、分布趋势、缺失值、异常值等

#!/usr/bin/python

import pandas as pd
import numpy as np

def getTopValues(series, top = 5, reverse = False):
    """Get top/bottom n values

    Args:
        series (Series): data series
        top (number): number of top/bottom n values
        reverse (bool): it will return bottom n values if True is given

    Returns:
        Series: Series of top/bottom n values and percentage. ['value:percent', None]
    """
    itype = 'top'
    counts = series.value_counts()
    counts = list(zip(counts.index, counts, counts.divide(series.size)))

    if reverse:
        counts.reverse()
        itype = 'bottom'

    template = "{0[0]}:{0[2]:.2%}"
    indexs = [itype + str(i + 1) for i in range(top)]
    values = [template.format(counts[i]) if i < len(counts) else None for i in range(top)]

    return pd.Series(values, index = indexs)


def getDescribe(series, percentiles = [.25, .5, .75]):
    """Get describe of series

    Args:
        series (Series): data series
        percentiles: the percentiles to include in the output

    Returns:
        Series: the describe of data include mean, std, min, max and percentiles
    """
    d = series.describe(percentiles)
    return d.drop('count')


def countBlank(series, blanks = []):
    """Count number and percentage of blank values in series

    Args:
        series (Series): data series
        blanks (list): list of blank values

    Returns:
        number: number of blanks
        str: the percentage of blank values
    """
    if len(blanks)>0:
        isnull = series.replace(blanks, None).isnull()
    else:
        isnull = series.isnull()
    n = isnull.sum()
    ratio = isnull.mean()

    return (n, "{0:.2%}".format(ratio))


def isNumeric(series):
    """Check if the series's type is numeric

    Args:
        series (Series): data series

    Returns:
        bool
    """
    return series.dtype.kind in 'ifc'

def detect(dataframe):
    """ Detect data

    Args:
        dataframe (DataFrame): data that will be detected

    Returns:
        DataFrame: report of detecting
    """
    numeric_rows = []
    category_rows = []
    for name, series in dataframe.items():
        # 缺失值比例
        nblank, pblank = countBlank(series)
        # 最大类别取值占比
        biggest_category_percentage = series.value_counts(normalize=True, dropna=False).values[0] * 100
        if isNumeric(series):
            desc = getDescribe(
                series,
                percentiles=[.01, .1, .5, .75, .9, .99]
            )
            details = desc.tolist()
            details_index = ['mean', 'std', 'min', '1%', '10%', '50%', '75%', '90%', '99%', 'max']
            row = pd.Series(
                index=['type', 'size', 'missing', 'unique', 'biggest_category_percentage', 'skew'] + details_index,
                data=[series.dtype, series.size, pblank, series.nunique(), biggest_category_percentage, series.skew()] + details
            )
            row.name = name
            numeric_rows.append(row)
        else:
            top5 = getTopValues(series)
            bottom5 = getTopValues(series, reverse=True)
            details = top5.tolist() + bottom5[::-1].tolist()
            details_index = ['top1', 'top2', 'top3', 'top4', 'top5', 'bottom5', 'bottom4', 'bottom3', 'bottom2', 'bottom1']
            row = pd.Series(
                index=['type', 'size', 'missing', 'unique', 'biggest_category_percentage'] + details_index,
                data=[series.dtype, series.size, pblank, series.nunique(), biggest_category_percentage] + details
            )
            row.name = name
            category_rows.append(row)
    return pd.DataFrame(numeric_rows), pd.DataFrame(category_rows)

demo(数据来自:https://www.kaggle.com/competitions/home-credit-default-risk/data)

import os
import eda
import pandas as pd
import numpy as np

data_dir = "./"

df = pd.read_csv(os.path.join(data_dir, "bureau.csv"))
numeric_df, category_df = eda.detect(df)

在这里插入图片描述
在这里插入图片描述

3.2 缺失值处理(示例)

#连续特征
df[col].fillna(-df[col].mean(), inplace=True)
#离散特征
df[col].fillna('nan', inplace=True)

3.3 删除无用特征

def get_del_columns(df):
    del_columns = {}
    for index, row in df.iterrows():
        if row["unique"] < 2:
            del_columns[row["Feature"]] = "取值单一"
            continue
        if row["missing"] > 90:
            del_columns[row["Feature"]] = "缺失值数量大于90%"
            continue
        if row["biggest_category_percentage"] > 99:
            del_columns[row["Feature"]] = "取值最多的类别占比超过99%"
            continue
        del_columns[row["Feature"]] = "正常"
    return del_columns

3.4 异常值处理

Winsorizer算法(定义某个变量的上界和下界,取值超过边界的话会用边界的值取代):
在这里插入图片描述

class Winsorizer():
    """Performs Winsorization 1->1*

    Warning: this class should not be used directly.
    """    
    def __init__(self,trim_quantile=0.0):
        self.trim_quantile=trim_quantile
        self.winsor_lims=None
        
    def train(self,X):
        # get winsor limits
        self.winsor_lims=np.ones([2,X.shape[1]])*np.inf
        self.winsor_lims[0,:]=-np.inf
        if self.trim_quantile>0:
            for i_col in np.arange(X.shape[1]):
                lower=np.percentile(X[:,i_col],self.trim_quantile*100)
                upper=np.percentile(X[:,i_col],100-self.trim_quantile*100)
                self.winsor_lims[:,i_col]=[lower,upper]
        
    def trim(self,X):
        X_=X.copy()
        X_=np.where(X>self.winsor_lims[1,:],np.tile(self.winsor_lims[1,:],[X.shape[0],1]),np.where(X<self.winsor_lims[0,:],np.tile(self.winsor_lims[0,:],[X.shape[0],1]),X))
        return X_
winsorizer = Winsorizer (0.1)
a=np.random.random((10,2))
print("转化前: ", a)
winsorizer.train(a)
print("上界和下界: ", winsorizer.winsor_lims)
b = winsorizer.trim(a)
print("转化后: ", b)

在这里插入图片描述

4.总结

这篇文章只总结了EDA的常用做法,实际应用过程中还需要根据具体业务来做调整。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1013881.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言——数据在内存中的存储_学习笔记

引言 在C语言——二进制/移位操作符/位操作符_学习笔记一文中有提到&#xff0c;数据在内存中是以二进制的形式存储的&#xff0c;也就是0和1&#xff1b; 而整数的二进制表示方法有三种&#xff0c;原码、反码和补码&#xff0c;文中也有所提及 而关于浮点数&#xff0c;浮点数…

在PHP8中向数组添加元素-PHP8知识详解

在php8中向数组添加元素有多种方法&#xff0c;在这里主要讲解几个常用的方法&#xff1a;使用方括号[]添加元素、使用array_unshift()函数&#xff0c;向数组的头部添加元素、使用array_push()函数&#xff0c;向数组的尾部添加元素、使用array_splice()函数添加元素。 1、使用…

【C++】类和对象(中下)

前言&#xff1a; 上一篇文章&#xff0c;我们了解了类的默认成员函数——构造函数、析构函数、拷贝构造函数&#xff0c;这篇我们让我们接着了解。 一、赋值运算符重载&#xff1a; 1.运算符重载&#xff1a; C为了增强代码的可读性引入了运算符重载&#xff0c;运算符重载是…

数据科学的文本技术 Text Technology(IR信息检索、搜索引擎)

一、文章摘要 1. 内容 * Introduction to IR and text processing, system components * Zipf, Heaps, and other text laws * Pre-processing: tokenization, normalisation, stemming, stopping. * Indexing: inverted index, boolean and proximity search * Evaluation m…

测试进阶知识之零日攻击的发现和防御

零日攻击是指针对软件或系统中未公开&#xff08;或未被开发者知晓&#xff09;的漏洞进行的攻击。这些漏洞被称为零日漏洞&#xff0c;因为在被公开之前&#xff0c;它们对开发者或安全研究人员来说是未知的&#xff0c;所以没有足够的时间进行防御或修复。 发现零日漏洞 发…

数据集成:数据挖掘的准备工作之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

清华大学 邓俊辉数据结构 关于哈希表的章节

本来以为没有 但是搜索hash 发现被叫做散列表 所以在9.3节就可以找到了

Keepalived+LVS高可用集群

目录 一、keepalived介绍&#xff1a; 二、keepalived工具介绍&#xff1a; &#xff08;1&#xff09;管理 LVS 负载均衡软件&#xff1a; &#xff08;2&#xff09;支持故障自动切换&#xff1a; &#xff08;3&#xff09;实现 LVS 负载调度器、节点服务器的高可用性&…

HTML5教程之移动端Web页面布局

一、什么是移动端项目 顾名思义&#xff0c;运行在移动端的项目就称为移动端项目。那什么是移动端呢&#xff0c;主要是指我们的一些手持设备&#xff0c;最具有代表性的就是我们日常使用的手机和平板&#xff0c;当然还包括一些其他便携设备&#xff0c;如智能手表&#xff0c…

LVS keepalived实现高可用负载群集

目录 1 Keepalived及其工作原理 1.1 Keepalived体系主要模块及其作用&#xff1a; 2 LVSKeepalived 高可用群集部署 2.1 配置负载调度器&#xff08;主、备相同&#xff09; 2.1.1 配置keeplived&#xff08;主、备DR 服务器上都要设置&#xff09; 2.1.2 启动 ipvsadm 服…

重新认识交叉编译

1. 我以前对交叉编译的认知 引用正点原子的话来讲就是: 说得对&#xff0c;但是不全面&#xff0c;直到最近项目中遇到了一个例子我才重新认识什么是交叉编译。 2. build/host/target的概念 参考: Cross-Compilation (automake) 参考: Specifying Target Triplets (Autocon…

javaee之黑马乐优商城3

异步查询工具axios(儿所以时) vue官方推荐的ajax请求框架 新增品牌页面 如何找到上面这个页面 下面这个页面里面的新增商品弹窗 上面就是请求路径与请求方式 那么请求参数是什么&#xff1f; brand对象&#xff0c;外加商品分类的id数组cids &#xff08;这里其实不止就是添加…

腾讯mini项目-【指标监控服务重构】2023-07-31

今日已办 trace_id传播 关于如何使用 trace_id 创建 span 的思路 【暂未实现 & 测试】 调研 SpanProcessor 阅读源码的test 明日待办 根据 trace_id 创建 span&#xff0c;应该需要 parent span_id 才能有 trace 的树状 span 的关系

腾讯mini项目-【指标监控服务重构】2023-08-06

今日已办 feature/client_traces_profile 修改 consumer 4个阶段的 spankind将 profile 的 span 作为 root span&#xff0c;保持与 venus 的 follows from 的 link feature/profile-otelclient-metric 将 metric 部分使用新分支 push go.opentelemetry.io/otel/propagatio…

定时器类的编写与解析 —— TinyWebServer

定时器类的编写与解析 —— TinyWebServer 一、前言 定时器非常好写。就是链表加定时函数。搞懂他的作用就成。 定时器的作用是什么&#xff1f;什么是回调函数&#xff1f;用到的函数是什么&#xff1f; 二、问题回答 Ⅰ、定时器的作用是什么&#xff1f; 处理非活跃的连…

坦克大战设计与实现

摘 要 J2SE是近年来随着各种不同技术的发展&#xff0c;尤其是编程语言飞速发展而诞生的一项新的开发语言。随着信息技术的飞速发展&#xff0c;计算机的使用也日渐普及&#xff0c;本文从实际应用出发&#xff0c;向大家介绍坦克大战游戏的设计与实现。Eclipse平台模拟器开发调…

华为数通方向HCIP-DataCom H12-831题库(单选题:21-40)

第21题 R3与R1的IS-IS邻居没有建立,根据本图的信息,可能的原因是? A、R3与R1的IIH认证失败 B、R3与R1的System ID重复 C、R3与R1的IS-Level不匹配 D、R3与R1的互连接口circuit-type不匹配 答案: A 解析: 从图中的Bad Authentiaction 信息可以看出R3与R1的IIH认证失败失败…

一生一芯16——安装pandoc使jupyter notebook转pdf

目的 希望导出jupyter notebook文档翻译 从这里导出pdf&#xff0c;但显示我没有安装pandoc&#xff0c;故安装pandoc 安装Pandoc 下载对应安装包 https://github.com/jgm/pandoc/releases 下载完成后&#xff0c;在目录中运行程序如下&#xff1a; 你需要解压下载的文件。…

windows10使用wheel安装tensorflow2.13.0/2.10.0(GPU版本) (保姆级教程)

安装过程 安装虚拟环境安装virtualenv安装满足要求的python版本使用virtualenv创建指定python版本的虚拟环境 安装tensorflow安装tensorflow-docs直接下载使用wheel下载 在VSCode编辑器中使用虚拟环境下的python解释器&#xff0c;并使用tensorflow常见错误 注意&#xff1a; t…

Python stomp 发送消息无法显示文本

我们向消息服务器通过 stomp 发送的是文本消息。 当消息服务器发送成功后&#xff0c;消息服务器上的文本没有显示&#xff0c;显示的是 2 进制的数据。 如上图&#xff0c;消息没有作为文本来显示。 问题和解决 消息服务器是如何判断发送的小时是文本还是二进制的。 根据官…