作者:包寒吴霜

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

知乎: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语言入门及数据挖掘回复 人工智能     三个月入门人工智能回复 数据分析师  数据分析师成长之路 回复 机器学习      机器学习的商业应用回复 数据科学      数据科学实战回复 常用算法      常用数据挖掘算法

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

c++如何把字符串转为变量名_如何优雅地计算多变量相关推荐

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

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

  2. c语言 把字符串转换为变量名_如何将抓取下来的unicode字符串转换为中文

    如果抓取的数据是json数据,那么直接将抓取的数据用json格式输出出来就行了.如下: response = requests.get(url, headers=self.headers).json( ...

  3. 通过反射将变量值转为变量名本身

    通过反射将变量值转为变量名本身 这是.NET反射的一个有趣小例子:  通过反射将变量值转为变量名本身. 当然要先添加命名空间:using System.Reflection; 示例代码如下: clas ...

  4. python的变量名有哪些_【python字符串做变量名的方法有哪些?这些方法对python应用很重要】- 环球网校...

    [摘要]python的功能都是建立在代码之上的,不过你知道python字符串做变量名的方法有哪些?这些方法对python应用很重要,如果你想学好python,那么本文内容一定要自己试试,毕竟实践出真知 ...

  5. python字符串定义变量名_python 将字符串作为变量名

    原博文 2019-10-12 16:43 − Python中如何使用字符串当作变量名 > 1.使用字符串指代变量名.> 比如说,有两个变量 a="bbb"和bbb={& ...

  6. python 将字符串作为变量名

    1.使用字符串指代变量名. 比如说,有两个变量 a="bbb"和bbb={"c":1},引用a如何得到{"c":1},也就是a的值'bbb' ...

  7. 转载:matlab 字符串和变量名互换

    原创文章,欢迎转载.转载请注明:转载自 祥的博客 原文链接:https://blog.csdn.net/humanking7/article/details/80628757 1. 问题引出 2 情况 ...

  8. shell 使用字符串拼接变量名

    shell 使用字符串拼接变量名 # 定义好要用的变量 REMOTE_SERVER_dev: "gitlab-runner@192.168.1.6:/data/build"# 生成 ...

  9. python遍历字典键值做变量名 字符串做变量名

    目录 1. exec 2. vars() 3. 全局变量globals() 感谢! [简书]Python中如何将字符串作为变量名 1. exec exec执行字符串命令.目前var和globals都不 ...

最新文章

  1. oracle 使用nfs挂载的目录不能进行归档
  2. html锚点(mao dian)--特殊的超链接
  3. SteamVR追踪技术有多火? 半数开发者来自非游戏行业
  4. Aop获取bean的过程---spring debug
  5. 企业形象广告的几个突破要点
  6. matlab cell,fix,floor,round取整的几种方式
  7. 子元素浮动,父元素高度为0现象解释和原理浅见
  8. 【计算机视觉】exe视频转mp4、采集视频中图片记录、删除ABC看图王等软件
  9. 我儿子今年15周岁,学习不好,去年上的高职,今年我犹豫是让他继续上,还是学个手艺?...
  10. Win10磁盘有很多磁盘0分区
  11. canvas图片合成
  12. snaker并行任务示例
  13. 新冠肺炎早期的10个症状 新冠肺炎1-14天症状特征
  14. codeforces 1520E Arranging The Sheep
  15. 容联智能云联络中心携手学而思 助力在线教育高速成长
  16. java基础之TreeMap
  17. 《穷爸爸和富爸爸》读后感
  18. github配置ssh key密钥的方法
  19. 小尾羊的qt学习之路,01课,基础芝士
  20. Macfee 卸载过程

热门文章

  1. 一文学会Maven的版本发布
  2. 如何看待消息中间件的选型
  3. uiuc工程学院计算机,UIUC计算机工程专业排名2020年
  4. 深度学习损失函数大全
  5. torch 归一化,momentum用法详解
  6. opencv openpose
  7. opencv 图像分割
  8. python下载mp4
  9. 给定a、b两个文件,各存放50亿个url,每个url各占64字节
  10. python 矩形补正方形