作者:包寒吴霜

中科院心理所硕士在读(名字/人格/社会/文化心理学)

知乎:https://www.zhihu.com/people/psychbruce

社会科学研究经常会遇到“超多变量”的情况——多量表、多维度、多题项,以及复杂的正反计分题……如何更高效地计算量表总分?如何更简洁地进行反向计分?

本文将为大家分享如何使用R语言(data.table包 + 自编函数)优雅地计算多变量。

当我们的数据中存在成百上千个变量时,不仅变量管理存在一定的难度,而且变量计算也会变得比较复杂。如果使用R来处理,有哪些现存的方法呢?

  • dplyr包的mutate函数(需再次赋值给data)

1data=mutate(data, X=x1+x2+x3, Y=y1+y2+y3)
  • data.table包的“:=”函数(原地更新,无需赋值)

1# 单变量计算2data[, X:=x1+x2+x3]3# 多变量同时计算4data[, ":="(X=x1+x2+x3, Y=y1+y2+y3)]

变量少还好说,然而,一旦遇到几十个甚至几百个变量,我们都希望利用更简便的方法来计算总分或平均分,而不是一个个敲变量名。

首先,直接使用sum(...)或mean(...)是行不通的,大家可以自行尝试(算出来的其实是每一列的总分而不是每一行的总分)。实际上,我们需要用mapply把相关函数施加于各个变量上,这样才能分别对每一行计算总分:

1data[, ":="(Xsum=mapply(sum, x1, x2, x3))]

这只是一个初步的解决思路,但依然尚未解决多变量的问题——我们并不想一个个敲变量名

于是乎,针对大家经常遇到的一些变量计算需求,我编制了相应的R函数,既可以用于普通的data.frame(mutate),也可以用于data.table(:=)。

下面以计算平均值为例,介绍自编的MEAN函数的基本用法:

1data[, ":="(Xmean1=MEAN(data, "x", 1:50),2            Xmean2=MEAN(data, vars=c("x1", "x2", "x3")),3            Xmean3=MEAN(data, varrange="x1:x50"),4            Xmean4=MEAN(data, "x", 1:50, rev=41:50, likert=1:7))]

MEAN的第一个参数为原来的数据(data.frame或data.table),后面的若干参数用来定义变量范围和反向计分题:

  • 对于有规律的变量名,如x1-x50,只需要定义var="x"和item=1:50即可(此为推荐用法,并且var和item参数名可省略)

  • 或者可以通过vars具体列出参与计算的变量(字符串向量)

  • 另外还可以通过varrange="x1:x50"或varrange=c("x1","x50")的形式定义变量的起止范围
    【提示:此时的1和50不代表数字上的连续范围,也就是说,varrange定义的起止范围是数据中变量的原始位置,如果原始变量的后缀数字是乱序排列的,则推荐使用var和item定义】

  • 如果涉及反向计分题,只需要通过rev参数定义哪些题目反向计分(可以是单个数字、单个字符串、数字向量、字符串向量),并通过likert参数定义题目是几点量表(例如1-7点的量表,设置likert=1:7或者likert=c(1, 7)均可)

MEAN函数的源代码如下(复制并运行即可使用):

 1MEAN=function(data, var=NULL, items=NULL, 2              vars=NULL, 3              varrange=NULL, 4              rev=NULL, likert=NULL, 5              na.rm=TRUE) { 6  Mean=function(...) mean(c(...), na.rm=na.rm) 7  if(!is.null(varrange)) { 8    dn=names(data) 9    if(length(varrange)==1) varrange=strsplit(varrange, ":")[[1]]10    varMin=varrange[1]11    varMax=varrange[length(varrange)]12    vars=dn[which(dn==varMin):which(dn==varMax)]13  } else {14    if(is.null(vars)) vars=paste0(var, items)15  }16  if(is.character(rev)) rev=which(vars %in% rev)17  vars=paste(deparse(substitute(data)), vars, sep="$")18  pre=rep("", length(vars))19  pre[rev]=ifelse(is.null(likert), "", paste0(min(likert)+max(likert), "-"))20  varlist=paste0(pre, vars)21  eval(parse(text=paste0("mapply(Mean, ", paste(varlist, collapse=", "), ")")))22}

除了MEAN之外,还有其他的几个自编函数,用法与MEAN类似,包括SUM(计算总分)、COUNT(统计某个值在多个变量中的出现次数)、CONSEC(统计多个变量中连续相同数字出现最多的个数):

 1SUM=function(data, var=NULL, items=NULL, 2             vars=NULL, 3             varrange=NULL, 4             rev=NULL, likert=NULL, 5             na.rm=TRUE) { 6  Sum=function(...) sum(..., na.rm=na.rm) 7  if(!is.null(varrange)) { 8    dn=names(data) 9    if(length(varrange)==1) varrange=strsplit(varrange, ":")[[1]]10    varMin=varrange[1]11    varMax=varrange[length(varrange)]12    vars=dn[which(dn==varMin):which(dn==varMax)]13  } else {14    if(is.null(vars)) vars=paste0(var, items)15  }16  if(is.character(rev)) rev=which(vars %in% rev)17  vars=paste(deparse(substitute(data)), vars, sep="$")18  pre=rep("", length(vars))19  pre[rev]=ifelse(is.null(likert), "", paste0(min(likert)+max(likert), "-"))20  varlist=paste0(pre, vars)21  eval(parse(text=paste0("mapply(Sum, ", paste(varlist, collapse=", "), ")")))22}232425COUNT=function(data, var=NULL, items=NULL,26               vars=NULL,27               varrange=NULL,28               value=NA) {29  Count=function(...) sum(c(...), na.rm=TRUE)30  if(!is.null(varrange)) {31    dn=names(data)32    if(length(varrange)==1) varrange=strsplit(varrange, ":")[[1]]33    varMin=varrange[1]34    varMax=varrange[length(varrange)]35    vars=dn[which(dn==varMin):which(dn==varMax)]36  } else {37    if(is.null(vars)) vars=paste0(var, items)38  }39  vars=paste(deparse(substitute(data)), vars, sep="$")40  if(is.na(value)) {41    varlist=paste0("is.na(", vars, ")")42  } else {43    varlist=paste0(vars, "==", value)44  }45  eval(parse(text=paste0("mapply(Count, ", paste(varlist, collapse=", "), ")")))46}474849CONSEC=function(data, var=NULL, items=NULL,50                vars=NULL,51                varrange=NULL,52                values=0:9) {53  Conseq=function(string, number=values) {54    # Consecutive Identical Digits55    require(stringr)56    pattern=paste(paste0(number, "{2,}"), collapse="|")57    ifelse(grepl(pattern, string), max(nchar(str_extract_all(string=string, pattern=pattern, simplify=TRUE))), 0)58  }59  if(!is.null(varrange)) {60    dn=names(data)61    if(length(varrange)==1) varrange=strsplit(varrange, ":")[[1]]62    varMin=varrange[1]63    varMax=varrange[length(varrange)]64    vars=dn[which(dn==varMin):which(dn==varMax)]65  } else {66    if(is.null(vars)) vars=paste0(var, items)67  }68  vars=paste(deparse(substitute(data)), vars, sep="$")69  varlist=vars70  eval(parse(text=paste0("mapply(Conseq, paste0(", paste(varlist, collapse=", "), "))")))71}

最后,我们以一个具体的例子来综合演示上述函数的用法。在下面的这个data.table中,我特意将x2和x4的位置对调了,大家可以自行体会不同参数之间的微妙差别(如var、vars、varrange)

 1d=data.table(x1=1:5, x4=c(2,2,5,4,5), x3=c(3,2,NA,NA,5), x2=c(4,4,NA,2,5), x5=c(5,4,1,4,5)) 2#    x1 x4 x3 x2 x5 3# 1:  1  2  3  4  5 4# 2:  2  2  2  4  4 5# 3:  3  5 NA NA  1 6# 4:  4  4 NA  2  4 7# 5:  5  5  5  5  5 8 9d[,":="(n.na=COUNT(d, "x", 1:5, value=NA),10        n.2=COUNT(d, "x", 1:5, value=2),11        sum=SUM(d, "x", 1:5),12        mean1=MEAN(d, "x", 1:5),13        mean2=MEAN(d, vars=c("x1", "x4")),14        mean3=MEAN(d, varrange="x1:x2", rev="x2", likert=1:5),15        cons1=CONSEC(d, "x", 1:5),16        cons2=CONSEC(d, varrange="x1:x5"))]17#    x1 x4 x3 x2 x5 n.na n.2 sum mean1 mean2 mean3 cons1 cons218# 1:  1  2  3  4  5    0   1  15   3.0   1.5     2     0     019# 2:  2  2  2  4  4    0   3  14   2.8   2.0     2     2     320# 3:  3  5 NA NA  1    2   0   9   3.0   4.0     4     0     021# 4:  4  4 NA  2  4    1   1  14   3.5   4.0     4     2     222# 5:  5  5  5  5  5    0   0  25   5.0   5.0     4     5     5

Tips:三种定义变量的方式选择其一即可,分别适用于不同需求——

  • var和item会将变量按照item的数字顺序重新排列(在函数内部其实是paste了var和item)

  • vars则以该参数实际定义的顺序为准

  • varrange定义的是起止位置的变量(因此在本例中“x1:x2”实则对应了“x1, x4, x3, x2”四个变量)

更多实用函数,请访问作者的GitHub:

https://github.com/psychbruce/stats/blob/master/BruceFunctions.R

公众号后台回复关键字即可学习

回复 爬虫            爬虫三大案例实战  回复 Python       1小时破冰入门

回复 数据挖掘     R语言入门及数据挖掘回复 人工智能     三个月入门人工智能回复 数据分析师  数据分析师成长之路 回复 机器学习      机器学习的商业应用回复 数据科学      数据科学实战回复 常用算法      常用数据挖掘算法

万水千山总是情,点个 “好看” 行不行!!!

R 回归 虚拟变量na_如何优雅地计算多变量相关推荐

  1. R 回归 虚拟变量na_互助问答第85期:虚拟变量和空间面板回归问题

    问题一:设置虚拟变量如何做工具变量处理 使用tobit模型回归时,被解释变量为连续变量,解释变量为分类变量,因研究重点需要将分类变量具体分析,因此将解释变量虚拟变量处理,回归时命令为tobit y i ...

  2. r语言清除变量_如何优雅地计算多变量 | R语言进阶

    社会科学研究经常会遇到"超多变量"的情况--多量表.多维度.多题项,以及复杂的正反计分题--如何更高效地计算量表总分?如何更简洁地进行反向计分?传统的统计工具(Excel.SPSS ...

  3. R 回归 虚拟变量na_工具amp;方法 | R语言机器学习包大全(共45个包)

    机器学习,是一门多学科交叉的人工智能领域的分析技术,它使用算法解析数据,从中学习,然后对世界上的某件事情做出决定或预测. 目前,常见机器学习的研究方向主要包括决策树.随机森林.神经网络.贝叶斯学习和支 ...

  4. R 回归 虚拟变量na_R语言 | 生存分析之R包survival的单变量和多变量Cox回归

    生存分析之R包survival的单变量和多变量Cox回归续前文生存分析(Survival Analysis). 在前文初步简介了生存分析的概念,以及展示了一种生存分析模型Kaplan-Meier的使用 ...

  5. c++如何把字符串转为变量名_如何优雅地计算多变量

    作者:包寒吴霜 中科院心理所硕士在读(名字/人格/社会/文化心理学) 知乎:https://www.zhihu.com/people/psychbruce 社会科学研究经常会遇到"超多变量& ...

  6. R语言定量方法:回归,虚拟变量和交互项,假设检验:F 检验、AIC 和 BIC分析学生成绩数据带自测题

    最近我们被客户要求撰写关于学生成绩的研究报告,包括一些图形和统计输出. 回归假设 省略变量偏差 如果真实模型包括X 1 和X 2 ,但我们忘记了X 2,那么 - 在某些情况下 - 对X的估计将会有偏差 ...

  7. R语言与虚拟变量模型

    学习笔记 参考书籍:<计量经济学>-李子奈:<统计学:从数据到结论>-吴喜之: 虚拟变量模型 许多变量是可以定量度量的,如需求量.价格等,但也有一些因素无法定量度量,如职业.性 ...

  8. R语言一般线性模型(涉及因变量是虚拟变量(哑变量))

    R语言的一般线性模型 R语言的一般线性模型用函数:lm(),即可轻松实现. 例子 建立一般线性模型 NC.glm1 = lm(fmri.SFG_R_CerebellumGM_L ~ age + gen ...

  9. r语言 分类变量 虚拟变量_R语言中的变量

    r语言 分类变量 虚拟变量 R语言| 变数 (R Language | Variables) In the previous tutorial, we have come across the bas ...

最新文章

  1. eclipse 模版的使用
  2. Linux 安装json神器 jq
  3. 【JAVA SERVLET 开发系列之二】创建WEBAPP详细步骤,通过SERVLET实现HTTP简单交互
  4. 云云协同解决方案全景图发布 华为云助力科技企业云上创新
  5. 【华为云技术分享】《跟唐老师学习云网络》 - Veth网线
  6. python 列表 元祖 字典,Python 列表、元组、字典
  7. canvas背景效果
  8. 知识分享:C语言语法总结,初学者可收藏
  9. ATP-EMTP中变压器联结方式与电压的关系
  10. 极限学习机Python的代码实现
  11. 25th Sept 2014:《数学分析八讲读书笔记》
  12. 【CPRI】(1)CPRI基本概念和相关术语
  13. python unrar问题_python利用unrar实现rar文件解压缩
  14. 服务器系统如何截图,电脑截图的快捷键是什么,小编告诉你电脑怎么截图
  15. 前端之CSS篇(二)——CSS复合选择器及元素的显示模式和背景属性
  16. win10 删除文件好慢解决方法
  17. php挂载webdav,PHP上传文件到WebDav
  18. 通用Mapper注解方式实现动态SQL
  19. 批量本地英语文档翻译软件
  20. 基于RNN的短期股票预测

热门文章

  1. Java的基础数据类型
  2. 不同域名cookie共享_cookie在二级域名间共享完成sso
  3. python函数修饰器_Python函数装饰器指南
  4. python操作文件的库_Python使用pyshp库读取shapefile信息的方法
  5. MySQL最高每秒57万写入,带你装X,带你飞!
  6. reentrantLock 和 synchronized 哪个性能高?
  7. beanfactorypostprocessor_Spring源码分析(六)容器的扩展点(BeanFactoryPostProcessor)
  8. (Mybatis)缓存
  9. 关于排序速度效率数组集合选择那点事
  10. 白话解析:一致性哈希算法 consistent hashing