非计算机背景但是想从事医学AI研究,需要掌握的编程语言|个人观点·24-11-08

时间:2024-11-09 07:05:13

小罗碎碎念

目前,我们从事医学AI研究的,接触的最多的两种编程语言应该就是R和Python了。那么初学者很容易提出一个疑问,**我想从事医学AI相关的研究的话,应该学哪些编程语言呢?**在文章的开头,我可以先给出自己的观点——两个都要学。

自己配的图,是不是还挺具有视觉冲击力的,哈哈

有的人可能觉得两个都要学太麻烦了,但是,我们冷静下来,想想自己在研究什么,就知道其实这是无法避免的。在传统的临床研究中,我们常用的就是R,用来做统计分析,画一些漂亮的图。在机器学习和人工智能兴起以后,Python异军突起,开始在数据分析、数据可视化以及图像处理领域大放异彩。

不过对于初学者,甚至是昨晚的我来说,要想具体说清楚R和Python的区别以及各自的用途,都还是很困难的,所以我决定写一篇推送,帮助自己,也帮助初学者建立起两种编程语言之间的联系,从而实现二者的交替使用,最后让自己的科研任务得到高效的完成!


一、引言

在工业界和学术界,多种开源编程语言,尤其是R和Python,被广泛应用于统计分析、数据挖掘和机器学习领域。

相较于大多数商业软件和编程语言在执行统计过程时提供的单一方式,开源编程语言拥有多个库和包,能够以多种方式完成同一分析任务,但结果往往有所差异。由于这些库和包在实现上的不同,即使应用相同的统计方法,也可能导致完全不同的解决方案。

因此,在利用开源编程语言进行统计分析时,库和包的选择应充分考虑其可靠性和准确性。然而,大多数用户往往默认所选择的库和包能够产生准确的统计分析结果。

根据过往实际经验,R中的stats包和Python中的statsmodels库在单变量汇总统计方面差距不大。但是Python的scikit-learn库在ANOVA分析(方差分析)中产生最准确的结果,因此推荐用于ANOVA分析。在线性回归分析的库和包评估中,R的stats包表现出更高的可靠性、准确性和灵活性,因此推荐用于线性回归分析。


二、编码风格

明确的编码风格指南对于保持代码的一致性、可读性和效率至关重要。

2-1:全局命令

全局命令是应用于整个软件环境的设置和配置。这些命令确立了默认行为和选项,这些选项在会话之间持续存在,确保软件每次使用时都能一致地操作。它们通常包括内存分配、显示选项、文件路径以及其他环境特定的偏好设置。


R

在R中,可以全局设置某些选项以保持一致性和简化工作流程。这些设置可以添加到主目录中的R配置文件(.Rprofile)。

  • options(stringsAsFactors = FALSE):防止字符串自动转换为因子。
  • options(digits = 3):设置显示数字时的默认位数。
  • library(tidyverse):加载用于数据操作和可视化的包集合。

在R中创建.Rprofile文件

可以创建一个.Rprofile文件并保存在主目录中。R启动时会自动运行此文件,允许每次R启动时设置自定义配置。

.Rprofile中的示例命令包括:

  • options(stringsAsFactors = FALSE)
  • options(digits = 3)
  • library(tidyverse)

Python

在Python中,可以使用启动脚本来管理配置设置,以保持一致性和简化工作流程。

import numpy as np:导入numpy库以进行数值操作。

import pandas as pd:导入pandas库以进行数据操作。

pd.set_option('display.max_columns', None):配置pandas显示所有列。

pd.set_option('display.precision', 3):设置显示数值的精度。


2-2:代码架构

在代码的前几行包含关键摘要信息,如作者、日期、目的、版本/最后更新日期。

通过插入clearset more off等命令来设置环境。

将代码组织为多个部分(例如,设置、加载数据、合并数据等),清晰地标注每个独立任务并记录所做决策。

R

头部信息

#-------------------------------------------------------- 

# 作者:罗小罗同学 

# 日期:2024-11-08 

# 目的:R vs Python 

# 版本/最后更新:1.0 / 2024-11-08 

#-------------------------------------------------------- 

环境设置

rm(list = ls()) 
options(stringsAsFactors = FALSE) 

代码组织

#-------------------------------------------------------- 

# 设置 

#-------------------------------------------------------- 

# 加载所需包并设置全局选项 

library(tidyverse) 
#-------------------------------------------------------- 

# 加载数据 

#-------------------------------------------------------- 
data <- read_csv("data/raw/mydata.csv") 
#-------------------------------------------------------- 

# 合并数据 

#-------------------------------------------------------- 
otherdata <- read_csv("data/clean/otherdata.csv") 
merged_data <- left_join(data, otherdata, by = "id") 
#-------------------------------------------------------- 

# 数据清洗 

#-------------------------------------------------------- 

# 生成新变量并进行标注 

merged_data <- merged_data %>% 
mutate(new_var = old_var * 2) %>% 
rename(Doubled_Old_Var = new_var) 
#-------------------------------------------------------- 

# 分析 

#-------------------------------------------------------- 
model <- lm(new_var ~ another_var, data = merged_data) 
#-------------------------------------------------------- 

# 输出 

#-------------------------------------------------------- 
write.csv(merged_data, "results/output.csv") 

Python

头部信息

"""

--------------------------------------------------------

作者:罗小罗同学
日期:2024-11-08 
目的:R vs Python

版本/最后更新:1.0 / 2024-11-08 
-------------------------------------------------------- 

""" 

环境设置

import numpy as np 
import pandas as pd

# 设置显示选项 

pd.set_option('display.max_columns', None) 
pd.set_option('display.precision', 3) 

代码架构

# 导入所需库并设置全局选项 

#-------------------------------------------------------- 

# 加载数据 

#-------------------------------------------------------- 
data = pd.read_csv("data/raw/mydata.csv") 
#-------------------------------------------------------- 

# 合并数据 

#-------------------------------------------------------- 
otherdata = pd.read_csv("data/clean/otherdata.csv") 
merged_data = pd.merge(data, otherdata, on="id") 
#-------------------------------------------------------- 

# 数据清洗 

#-------------------------------------------------------- 

# 生成新变量并进行标注 

merged_data['new_var'] = merged_data['old_var'] * 2 
merged_data = merged_data.rename(columns={'new_var': 'Doubled_Old_Var'}) 
#-------------------------------------------------------- 

# 分析 

#-------------------------------------------------------- 
import statsmodels.api as sm 
X = merged_data['another_var'] 
y = merged_data['Doubled_Old_Var'] 
X = sm.add_constant(X) 
model = sm.OLS(y, X).fit() 
#-------------------------------------------------------- 

# 输出 

#-------------------------------------------------------- 
merged_data.to_csv("results/output.csv", index=False)

2-3:注释

代码注释至关重要:它使得其他人(或我们自己稍后)更容易理解代码各部分的目标和实现方法。

注释提高了代码的可读性,通过允许代码的部分内容临时失效来便利调试过程,并为复杂逻辑提供上下文或解释。有效的注释可以显著提升协作和维护效率,确保代码库随时间推移仍保持可理解性和可管理性。

R

在R中,注释用于解释代码并提高可读性。使用#进行单行注释。

# 遍历数字1到10

for (i in 1:10) { 

# 检查数字是偶数还是奇数

if (i %% 2 == 0) { 
print(paste(i, "是偶数")) # 如果是偶数则打印
} else { 
print(paste(i, "是奇数")) # 如果是奇数则打印
} 
}

Python

在Python中,注释用于解释代码并提高可读性。

使用#进行单行注释,使用三引号''' ... '''进行多行注释(尽管三引号通常用于文档字符串)。

# 遍历数字1到10

for i in range(1, 11): 

# 检查数字是偶数还是奇数

if i % 2 == 0: 
print(f"{i} is even") # 如果是偶数则打印
else: 
print(f"{i} is odd") # 如果是奇数则打印
''' 
这是一个多行注释
使用三引号
'''

2-4:代码缩进

代码缩进对于提高可读性至关重要,它通过使逻辑流程和结构更易于追踪来实现。

缩进有助于视觉上区分不同的代码块,如循环、条件语句和函数,这对于理解和编辑代码至关重要。

在某些编程语言中,如Python,缩进不仅仅是用于提高可读性,而且在语法上具有意义,即如果没有正确的缩进,代码将无法正确运行。

一致的缩进实践还有助于研究人员和开发者之间的协作,确保代码库结构统一。


R

缩进可以提高代码的可读性,应一致地使用两个空格进行缩进

对齐代码块以使结构清晰。

image-20241108094133410


Python

Python使用缩进来定义代码块。遵循PEP 8建议,每个缩进级别使用四个空格

一致的缩进对于Python的语法是关键且必要的。
image-20241108094219641


2-5:运算符与空格的使用

在运算符(如 +, -, =, ==)周围适当留出空格可以提高代码的可读性,使其逻辑更易于理解和追踪。

这有助于快速识别表达式和操作,并减少因紧密排列的代码而导致的错误理解的可能性。一致的空格使用和正确的运算符应用还能提升代码的可维护性并便于调试,因为结构良好的代码更易于导航和修改。

R

在运算符周围留出空格以提高清晰度。这改善了代码的可读性和可维护性。

bmi <- weight_kg / (height_m ^ 2)
bmi[height_m == 0] <- NA 

而非:

bmi<-weight_kg/(height_m^2) 
bmi[height_m==0]<-NA

Python

遵循PEP 8指南,在运算符周围使用空格,但避免在括号、方括号或大括号内使用空格。这使得代码更具可读性,并与Python社区的广泛实践保持一致。

bmi = weight_kg / (height_m ** 2) 
if height_m == 0: 
  bmi = None 

而非:

bmi=weight_kg/(height_m**2) 
if(height_m==0): 
  bmi=None 

三、可复现性

3-1:设置随机种子和排序

通过设置随机种子确保结果的稳定性

设置随机种子可以确保随机过程的结果是可复现的。这对于数据分析的一致性至关重要,尤其是在运行包含随机化的模拟和算法时。

  • R:使用 set.seed 函数
  • Python:使用 numpy.random.seed 函数

为防止结果因观察顺序不同而产生的变异,进行一致的数据排序

一致的数据排序可以防止因观察顺序不同而导致的结果变异。这在将数据分割为训练集和测试集或执行顺序分析时尤为重要

  • R:使用 dplyr 包中的 arrange 函数
  • Python:使用 pandas 中的 sort_values 方法

3-2:文件管理与组织

维持清晰有序的目录结构以存放数据、脚本和结果

有序的文件管理有助于提高工作效率和协作。清晰的数据、代码和结果目录结构有助于轻松定位和管理文件。文件管理结构的一个示例包括以下内容:

  • code:此文件夹包含所有脚本,每个脚本文件名前都有数字前缀,指示其运行顺序;将旧版本的代码存档在 archive/ 子文件夹下(文件名后缀为最后修改日期,例如 1_import_clean_2024-11-08.do),便于在需要时追踪更改。

    • 1_import_clean.do:导入或清理数据,并标注所有原始变量。

    • 2_create_variables.do:创建新变量并标注。

    • 3_run_diagnostics.do:运行诊断以检查数据质量和假设。

    • 4_run_models_and_visualize.do:运行回归模型并创建表格和图形以可视化结果。

  • data:此文件夹及其子文件夹包含数据文件;这些子文件夹提供了结构:

    • raw/:原始数据文件。

    • temp/:处理过程中创建的中间数据文件。

    • final/:最终清理和处理后的数据文件。

  • documentation:此文件夹包括与数据和分析相关的文档,例如:

    • 分析结果。
    • 数据相关文档。
    • 数据用户协议。

3-3:记录分析工作流程

为数据处理和分析工作流程的每一步编写详细文档

分析工作流程每一步的详细记录确保了透明度和可复现性。这包括记录数据来源、处理步骤、分析方法和分析过程中所做的任何假设或决策。

可复现分析工具,如 Jupyter Notebooks 或 R Markdown,将代码、输出和叙述合并为一个文档。这种集成便于清晰地传达分析过程和结果,增强了可复现性和理解。


3-4:流程表

跟踪从初始数据集到最终分析样本的样本量演变至关重要。

这涉及记录数据处理的每个阶段,其中根据特定标准如排除规则、治疗分配和必要数据字段的完成情况进行调整。每个步骤都应清晰地说明过滤了多少观察值,以及这些观察值占原始数据集的百分比。

记录这些细节确保了数据清理过程的透明性,并有助于维护用于分析的最后数据集的完整性。这种做法还有助于理解数据处理决策对研究结果的影响。


四、数据加载

在数据分析中,经常遇到以不同格式存储的数据,如Excel、SAS数据集、CSV文件和纯文本。

将这些文件转换为适合分析的格式涉及使用特定于每种文件类型的库和工具。

例如,可以使用处理电子表格数据的库来读取和转换Excel文件,而SAS数据集可能需要使用专门的命令或包来正确读取。CSV和文本文件通常更简单,但仍需谨慎处理分隔符和编码。

  • R:使用如 readxl, haven, 和 data.table 等库来读写各种文件类型
  • Python:使用 pandas 库的 read_excel, read_csv 等函数

五、理解变量类型和格式

5-1:检查数据和变量

分析数据结构和变量类型

在数据分析中,理解数据的结构和类型至关重要。这包括识别变量的类型、它们的格式以及可能在进一步分析之前需要解决的任何不一致之处。

常见问题包括数值变量被导入为字符串、缺失值或错误的数据类型。


R

使用 str(), summary(), Hmisc::describe(), 和 psych::describe() 等函数。

  • str():显示R对象的内部结构,提供每个变量数据类型的详细信息。
  • summary():为数据集中的每个变量提供汇总统计。
  • Hmisc::describe():为每个变量提供详细描述,包括缺失值数量和唯一值。
  • psych::describe():提供详细的描述性统计,包括均值、标准差和其他汇总度量。

Python

使用 pandasdf.info(), df.describe(), df.dtypes, 和 df.isnull().sum() 等函数。

  • df.info():提供DataFrame的简洁概要,包括非空条目数量和数据类型。
  • df.describe():为数值列生成描述性统计。
  • df.dtypes:列出每列的数据类型。
  • df.isnull().sum():计算每列的缺失值数量。

5-2:调整变量类型

检查数据后,可能需要进行一些调整,尤其是如果原始数据集是从非数据文件格式导入的。

例如,一些数值变量可能被导入为字符串,并将需要转换为数值类型以在分析中使用。

R

  • as.numeric():将变量转换为数值。
  • dplyr::mutate():用于创建新变量或修改现有变量。
  • tidyr::replace_na():用指定值替换缺失值。

Python

  • pd.to_numeric():将参数转换为数值类型。
  • df.astype():将pandas对象强制转换为指定的数据类型。
  • df.fillna():使用指定方法填充NA/NaN值。

六、数据整理/准备

6-1:合并

使用各种连接技术组合数据集

合并数据集是基于一个共同的关键字段来组合数据集,这个关键字段指的是一个或多个标识唯一记录的变量(例如,CUSIP年份)。

内连接只返回匹配的记录(那些在两个数据集中都出现的记录),左连接返回左数据集(我们正在将其与其他数据集匹配的原始数据集)的所有记录以及右数据集(我们从中获取额外变量的补充数据集)的匹配记录,右连接则相反。

这些技术是整合不同数据集成为一个连贯整体的基础。


R

使用merge函数或dplyr包的left_joinright_joininner_joinfull_join函数。

  • left_join()保留左数据集的所有观察值
  • right_join()保留右数据集的所有观察值
  • inner_join()只保留两个数据集中都出现的观察值
  • full_join()保留两个数据集中的所有观察值。

Python

使用pandas库的merge函数。

  • pd.merge(left, right, how='inner', on='key')执行内连接
  • pd.merge(left, right, how='left', on='key')执行左连接
  • pd.merge(left, right, how='right', on='key')执行右连接
  • pd.merge(left, right, how='outer', on='key')执行全连接

6-2:模糊匹配

实施模糊匹配算法以合并非精确匹配的数据集

有时数据集需要基于非精确匹配进行合并,例如带有拼写错误或变体的名称。模糊匹配算法有助于识别相似但不完全相同的条目,从而实现更灵活的数据整合。

当没有唯一标识符可用时,模糊匹配非常有用。这种技术涉及找到数据集中近似匹配的字符串,并提供匹配的概率。如果可能,首选精确匹配,但模糊匹配在必要时非常有帮助。

通常,模糊匹配包括三个步骤:

  1. 字符串清洗:通过标准化空格、大小写和删除特殊字符来预处理匹配数据;这可能包括常见术语,如标题(例如,“Mrs.”)。
  2. 概率匹配:模糊匹配函数估计主数据中的观察值与使用数据中的观察值匹配的概率。
  3. 匹配审查:审查匹配以决定匹配成功的点(例如,匹配距离或分数阈值)。某些记录可能需要手动审查或匹配。

R

stringdist包或fuzzyjoin包。

  • stringdist:提供多种字符串距离算法用于模糊匹配。
  • fuzzyjoin:提供基于非精确匹配的表格连接函数。

Python

fuzzywuzzy库或difflib模块。

  • fuzzywuzzy:使用Levenshtein距离计算序列之间的差异。
  • difflib:提供用于比较序列的类和函数。

6-3:重塑与聚合

为满足分析需求,将数据转换成不同的形状

数据经常需要被重塑以适应特定的分析模型或可视化需求。重塑包括在宽格式和长格式之间转换数据,将表格从长格式转换为宽格式(透视表),以及将数据框从宽格式转换为长格式(熔化),以确保数据结构与预期分析相符合。

  • R:使用 tidyr 包中的 pivot_longerpivot_wider 函数,以及基础包中的 aggregate 函数。
  • Python:使用 pandas 库中的 meltpivot_table 函数。

6-4:扩展

通过复制或乘以现有数据点来添加新的数据点

扩展数据集可能涉及通过复制或乘以现有数据点来添加新行。这对于模拟场景、增加样本量或为特定分析准备数据非常有用。

  • R:使用 replicate 函数来复制行。
  • Python:使用 pandas 来连接 DataFrame 的副本。

在扩展过程中确保数据一致性

在扩展过程中保持数据一致性至关重要,以避免引入错误或偏差。数据一致性涉及对新数据点的仔细验证,并确保它们与现有数据结构无缝集成。


6-5:追加

将新的数据集添加到现有数据集中

追加数据集涉及将它们垂直堆叠,将一个数据集中的行添加到另一个数据集。当我们有来自不同时间或不同来源的相似结构的数据,并希望将它们合并成一个数据集时,这非常有用。

  • R:使用 rbind() 函数或 dplyr 包中的 bind_rows() 函数。
  • Python:使用 pandas 库中的 concat() 函数来追加 DataFrames。

七、数据清洗

7-1:唯一性与重复项

确定唯一变量集合以创建数据集的主键

建立主键对于数据完整性至关重要。识别唯一确定每个记录的变量组合,确保没有重复项,每个条目都是独特的。

  • R:使用 unique 函数在向量或数据框中找到不同的元素。
  • Python:使用 pandas 库中的 unique 方法获取列的唯一值。

解决重复项以维持数据质量的策略

解决重复项首先需要识别其原因。可能是数据生成错误的结果(例如,原始数据集可能意外创建了重复项),或者我们可能没有完全理解我们的数据集(例如,如果我们忽略了那些记录之间的其他变量差异,看似重复的记录实际上可能并非如此)。

处理重复记录可能需要收集额外变量(使它们不再重复),合并记录(例如,如果我们有一个月的两个部分条目,我们希望将它们合并为该月的一个记录),或删除冗余记录。采取措施解决重复项后,确保剩余数据集无重复。

  • R:使用 dplyr 包中的 distinct 函数保留唯一行。
  • Python:使用 pandas 库中的 drop_duplicates 方法消除重复条目。

7-2:缺失值

识别缺失值并理解其影响

缺失数据可能会显著影响分析结果。识别缺失模式并理解其含义有助于选择适当的方法来处理它们。

  • R:使用 is.na 函数来查找缺失值,以及 mice 包来分析缺失模式。
  • Python:使用 pandas 中的 isnull 方法来识别缺失值,以及 missingno 库来可视化缺失数据模式。

插补技术

有时缺失值被编码为异常值,如“N/A”或“999”,在实施任何其他处理缺失值的方法之前,需要将这些值重新编码为缺失。

特别是当我们有理由相信缺失是由随机过程引起时,一种常见的方法是创建一个新变量,该变量取变量的值,但将缺失值重新编码为零或变量的平均值——并创建一个二元变量,当进行替换时编码为1,否则为0,并将此哑变量包含在包含重新编码变量的回归规范中。

重新编码变量的名称可以后缀“mz”(当将缺失值重新编码为零时)或“mm”(当将缺失值重新编码为平均值时);新二元变量可以后缀“miss”(例如,female_mz 和 female_miss)。

另一种选择是使用插补方法,该方法依赖于变量之间的数据模式来生成代理值,但一个缺点是这可能创建依赖于样本或模型的值,意味着它们较少具有普遍性;插补方法生成带有标准误差的估计值,因此通常直接与回归模型相关联,以适应独立变量值中的误差。

  • R:使用 Hmisc 包中的 impute 函数或 mice 包。
  • Python:使用 pandas 中的 fillna 方法进行简单插补,以及 sklearn 中的 SimpleImputer 类进行更高级的技术。

7-3:离群值

利用领域知识识别离群值

离群值是指与其他观测值显著偏离的数据点。识别离群值需要利用领域知识来识别异常高或低的值,并评估其有效性。我们需要判断哪些可能是数据错误,哪些是实际值。

错误值可以重新编码为缺失。由于数据分析旨在解释一般性关系,我们可能想要通过创建一个新变量来评估或减少实际值离群值的影响,该变量取旧变量的值,但我们会通过对离群值进行温莎化(用变量分布的顶部或底部值替换它们,例如第1或第99百分位数)或省略它们来重新编码,或者我们可以使用变量的对数版本(这会压缩离群值)。

  • R:使用 boxplot.stats 函数或 outliers
  • Python:使用 pandas 中的 describe 方法以及 matplotlibseaborn 的可视化工具

八、变量创建与标记

所有变量都应进行标记,当变量来自不同数据源时,标签应指明数据源。尽可能使变量名暗示其编码(例如,femalegender 更好;log_employmentsize 更好)。

8-1:命名与标记变量

使用标准后缀命名变量名(例如,_cat 表示分类变量,mz 表示缺失值被重新编码为零的变量,_mm 表示缺失值被重新编码为其样本均值的变量,_ln 表示对数变量,_lnp1 表示加1后取对数的变量)。

R

变量名应具有描述性,并使用小写字母。

在变量名中使用点 (.) 或下划线 (_) 分隔单词(例如,income.levelincome_level)。

避免使用R中已经保留的名称(例如,mean, data)。

使用 label 属性或 comment 函数提供额外的上下文。

使用 str() 创建变量名、类型和其他属性的摘要。

income_level <- total_income / total_population
attr(income_level, "label") <- "Per capita income for each individual in the population"
str(data_frame)

Python

遵循PEP 8 (https://peps.python.org/pep-0008/) 命名约定:变量名使用小写字母,单词之间用下划线分隔(例如,income_level, total_population)。

除循环计数器外,避免使用单个字母的变量。

使用有意义的名称,使代码自我解释。

Python没有内置的变量标记支持,但可以使用注释来提供上下文。

使用 df.info()df.describe() 创建变量名、类型和其他属性的摘要。

income_level = total_income / total_population

# Per capita income for each individual in the population

df.info()
df.describe()

8-2:连续变量与分类变量

区分连续变量与分类变量

连续变量表示具有有意义区间的数值,而分类变量表示离散的组或类别。

正确识别和区分这些类型对于适当的数据处理和分析至关重要。可以根据连续变量的区间或值创建基于区间的分类变量(例如,Stata的 recodeegen, cut 命令)。


正确编码和存储不同类型的变量

确保连续和分类变量被适当编码和存储,涉及使用适当的数据类型和编码方法,如数值编码用于连续变量,因子编码用于分类变量。

  • R:使用 factor 函数将分类变量转换为因子类型,并使用 table 函数进行值的选择。
  • Python:使用 pandas 中的 astype 方法将列转换为适当的数据类型,并使用 value_counts 方法进行值的选择。

8-3:二元(哑)变量

创建二元(哑)变量以表示分类变量的所有值

二元变量可用于表示分类变量的所有值,其中每个类别(值)被转换为单独的二元变量,指示该类别的存在或缺失。这在回归分析和其他统计模型中特别有用。

在回归模型中,我们必须省略一个这些二元变量作为参考(基线)类别;确保将这些二元变量的系数解释为偏离此参考(基线)类别。我们可以使用后回归工具,如Wald检验,来评估这些二元变量系数是否彼此不同。

  • R:使用 model.matrix 函数或 dummies 包创建二元变量。
  • Python:使用 pandas 库中的 get_dummies

九、探索性数据可视化

9-1:直方图、核密度图和箱线图

数据分布的可视化及模式识别

直方图、核密度图和箱线图(含须图)是用于可视化数据分布的图形方法。

理解每种方法的优势与局限

每种可视化方法都有其优势和局限性。直方图直观但受限于柱状尺寸,核密度图提供平滑的密度估计但对带宽敏感,箱线图擅长识别异常值但无法展示分布形状。

  • R:使用 histdensityboxplot 函数。
  • Python:使用 pandasmatplotlib 中的 hist 方法制作直方图,plot.kde 制作核密度图,以及 pandas 中的 boxplot 制作箱线图。

9-2:条形图

创建条形图以比较分类数据

条形图适用于比较类别的频率或计数。它们提供了一种清晰直观的方式来可视化组间差异。

  • R:使用 barplot 函数或 ggplot2 包制作条形图。
  • Python:使用 matplotlibseaborn 中的 bar 方法制作条形图。

9-3:散点图

视觉化两个连续变量之间的关系

散点图展示两个连续变量之间的关系,有助于识别趋势、模式和潜在的相关性。

在散点图上添加趋势线有助于可视化关系的整体方向。解释散点图涉及评估变量间关系的强度和性质。

  • R:使用 plot 函数或 ggplot2 包制作散点图。
  • Python:使用 matplotlibseaborn 中的 scatter 方法制作散点图。

9-4:线图

绘制时间序列数据以观察随时间的变化趋势

线图适用于可视化时间序列数据,展示值随时间的变化。它们有助于识别趋势、周期和模式。

  • R:使用 plot 函数或 ggplot2 包制作线图。
  • Python:使用 matplotlibseaborn 中的 plot 方法制作线图。

9-5:图表格式化

选择合适的颜色、标签和刻度

有效的格式化增强了可视化效果的清晰度和影响力。选择合适的颜色、标签和刻度确保了可视化易于理解和解释。

R

R中的 ggplot2 包提供了广泛的图形格式化功能,允许使用如 ggtitle 添加标题、xlab 添加x轴标签、ylab 添加y轴标签和 theme 进行整体样式定制等函数来定制图形的所有方面。

Python

Python中的 matplotlib 库提供了全面的图形格式化功能,通过如 plt.title 添加标题、plt.xlabel 添加x轴标签、plt.ylabel 添加y轴标签和 plt.legend 定制图例等方法来定制图表。


9-6:保存和导出图表

确保高质量输出以用于展示和报告

高质量的输出确保了可视化清晰且专业,提升了数据洞察的整体展示和沟通效果。

以多种格式(PNG、PDF、TIF)导出可视化

以不同格式导出可视化便于在报告、展示和出版物中使用。确保高质量输出保持了可视化在不同媒介中的完整性。

  • R:使用 ggplot2 包中的 ggsave 函数导出图表。
  • Python:使用 matplotlib 中的 savefig 方法导出可视化。

十、探索性数据分析

10-1:描述性统计

生成描述性统计数据(N、最小值、最大值、平均值、中位数、标准差)

描述性统计提供了数据的快速概览,包括中心趋势度量(平均值、中位数)和范围及离散度度量(最小值、最大值、标准差),有助于理解数据的分布和变异性。

  • R:使用 summary 函数。
  • Python:使用 pandas 中的 describe 方法。

10-2:相关性

使用相关系数评估变量之间的关系,以矩阵格式显示系数。

相关系数衡量两个变量之间关系的强度和方向。这有助于识别数据中的潜在关联和依赖关系。

  • R:使用 cor 函数。
  • Python:使用 pandas 中的 corr 方法。

10-3:假设检验以比较分布

理解假设和解释测试结果

每个假设检验都有其潜在的假设,如正态性和方差同质性。理解这些假设并正确解释结果对于从测试中得出有效结论是必要的。

假设检验涉及诸如卡方检验用于分类数据、方差分析用于比较多个组别之间的均值、T检验用于比较两个组别之间连续变量的均值以及比例检验用于比较两个组别之间二进制变量(平均值)的分数。这些测试有助于确定观察到的差异是否具有统计学意义。

  • R:使用 chisq.test 函数,aovt.test
  • Python:使用 scipy.stats 中的 chi2_contingency 函数,f_onewayttest_ind

十一、回归分析

11-1:回归诊断

在进行回归分析前,执行回归诊断和假设检验对于验证模型的正确性至关重要。

这些诊断有助于检测回归假设的违反情况,例如非线性、异方差性和多重共线性。特定的检验用于验证模型及其预测因子的显著性。

R中,使用 plot 函数检测非线性,lmtest 包中的 bptest 检验异方差性,car 包中的 vif 函数检验多重共线性。

Python中,使用 sns.scatterplot 函数检测非线性,het_breuschpagan 函数检验异方差性,variance_inflation_factor 函数检验多重共线性。


11-2:调整标准误差

考虑异方差性和聚类效应,通过调整标准误差来提高模型准确性。

面板数据中的聚类是指将具有共同特征的观测值分组。考虑聚类有助于提高模型准确性并使数据推断有效。

R中,使用 sandwich 包中的 cluster.vcov 函数或 plm 包中的 vcovHC 函数指定聚类标准误差。

Python中,在 statsmodels 库的 fit 方法中使用 cov_type='cluster' 选项指定聚类标准误差。


11-3:普通最小二乘法(OLS)回归

OLS回归通常用于估计具有连续因变量和一个或多个自变量的模型,它通过最小化观测值和预测值之间差异的平方和来估计模型参数。有时(主要由经济学家使用)用于估计具有二进制因变量的模型,此时称为线性概率模型(LPM)。

检查假设并解释系数:OLS回归依赖于线性性、独立性、同方差性和正态性等假设。在估计模型前检查这些假设可以提高结果的可靠性、有效性和稳定性。

R中,使用 lm 函数拟合线性模型,并通常指定稳健或聚类标准误差。

Python中,使用 statsmodels 库中的 OLS 方法,并通常指定稳健或聚类标准误差。


11-4:Logistic回归

使用Logistic回归对二进制结果变量进行建模,用于预测事件发生的概率。

Logistic回归系数的解释需要谨慎,常见的方法包括将系数指数化得到优势比(OR)和计算平均边际效应(AMEs)。

R中,使用 glm 函数并指定 family=binomial 参数,并通常指定稳健或聚类标准误差。

Python中,使用 statsmodels 库中的 Logit 方法或 sklearn 中的 LogisticRegression 类,并通常指定稳健或聚类标准误差。


11-5:泊松回归

泊松回归用于估计以计数变量为因变量的模型(事件发生的次数)。它假设计数变量的均值和方差相等,但(至少在面板数据应用中)即使这一条件不满足,也可以使用稳健标准误差。

泊松回归系数的解释需要谨慎,常见的方法包括:

(1)将系数指数化得到发生率比(IRR)

(2)使用 margins, dydx(var) 计算平均边际效应(AMEs)。

R:使用带有 family=poisson 参数的 glm 函数。

Python:使用 statsmodels 库中的 Poisson 方法。


11-6:回归后分析

在拟合回归模型后,我们可以检验模型内部系数之间以及不同样本或模型中系数(通常是同一变量)的假设比较。

这些检验有助于我们理解各种效应是否在统计上存在差异。常见的回归后检验是沃尔德检验;比较不同样本或模型中的系数,首先需要估计似乎不相关的回归。

R:使用 car 包中的 linearHypothesis 函数执行沃尔德检验,以评估关于回归模型系数的线性假设,systemfit 包允许进行似乎不相关的回归,以比较不同样本或模型中的系数。

Python:使用 statsmodels 库中的 wald_test 方法执行沃尔德检验,以评估关于回归模型系数的线性假设,seemingly_unrelated 模块允许进行似乎不相关的回归,以比较不同样本或模型中的系数。