c++如何把字符串转为变量名_如何优雅地计算多变量
作者:包寒吴霜
中科院心理所硕士在读(名字/人格/社会/文化心理学)
知乎: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++如何把字符串转为变量名_如何优雅地计算多变量相关推荐
- r语言清除变量_如何优雅地计算多变量 | R语言进阶
社会科学研究经常会遇到"超多变量"的情况--多量表.多维度.多题项,以及复杂的正反计分题--如何更高效地计算量表总分?如何更简洁地进行反向计分?传统的统计工具(Excel.SPSS ...
- c语言 把字符串转换为变量名_如何将抓取下来的unicode字符串转换为中文
如果抓取的数据是json数据,那么直接将抓取的数据用json格式输出出来就行了.如下: response = requests.get(url, headers=self.headers).json( ...
- 通过反射将变量值转为变量名本身
通过反射将变量值转为变量名本身 这是.NET反射的一个有趣小例子: 通过反射将变量值转为变量名本身. 当然要先添加命名空间:using System.Reflection; 示例代码如下: clas ...
- python的变量名有哪些_【python字符串做变量名的方法有哪些?这些方法对python应用很重要】- 环球网校...
[摘要]python的功能都是建立在代码之上的,不过你知道python字符串做变量名的方法有哪些?这些方法对python应用很重要,如果你想学好python,那么本文内容一定要自己试试,毕竟实践出真知 ...
- python字符串定义变量名_python 将字符串作为变量名
原博文 2019-10-12 16:43 − Python中如何使用字符串当作变量名 > 1.使用字符串指代变量名.> 比如说,有两个变量 a="bbb"和bbb={& ...
- python 将字符串作为变量名
1.使用字符串指代变量名. 比如说,有两个变量 a="bbb"和bbb={"c":1},引用a如何得到{"c":1},也就是a的值'bbb' ...
- 转载:matlab 字符串和变量名互换
原创文章,欢迎转载.转载请注明:转载自 祥的博客 原文链接:https://blog.csdn.net/humanking7/article/details/80628757 1. 问题引出 2 情况 ...
- shell 使用字符串拼接变量名
shell 使用字符串拼接变量名 # 定义好要用的变量 REMOTE_SERVER_dev: "gitlab-runner@192.168.1.6:/data/build"# 生成 ...
- python遍历字典键值做变量名 字符串做变量名
目录 1. exec 2. vars() 3. 全局变量globals() 感谢! [简书]Python中如何将字符串作为变量名 1. exec exec执行字符串命令.目前var和globals都不 ...
最新文章
- oracle 使用nfs挂载的目录不能进行归档
- html锚点(mao dian)--特殊的超链接
- SteamVR追踪技术有多火? 半数开发者来自非游戏行业
- Aop获取bean的过程---spring debug
- 企业形象广告的几个突破要点
- matlab cell,fix,floor,round取整的几种方式
- 子元素浮动,父元素高度为0现象解释和原理浅见
- 【计算机视觉】exe视频转mp4、采集视频中图片记录、删除ABC看图王等软件
- 我儿子今年15周岁,学习不好,去年上的高职,今年我犹豫是让他继续上,还是学个手艺?...
- Win10磁盘有很多磁盘0分区
- canvas图片合成
- snaker并行任务示例
- 新冠肺炎早期的10个症状 新冠肺炎1-14天症状特征
- codeforces 1520E Arranging The Sheep
- 容联智能云联络中心携手学而思 助力在线教育高速成长
- java基础之TreeMap
- 《穷爸爸和富爸爸》读后感
- github配置ssh key密钥的方法
- 小尾羊的qt学习之路,01课,基础芝士
- Macfee 卸载过程