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

6aa14dc494c78c79f361cdb5b4523445.png

社会科学研究经常会遇到“超多变量”的情况——多量表、多维度、多题项,以及复杂的正反计分题……如何更高效地计算量表总分?如何更简洁地进行反向计分?传统的统计工具(Excel、SPSS等)虽然也能解决这些问题,但在超多变量的情况下会比较繁琐。相反,R语言以其扩展包的强大功能和代码的极简风格,狂甩传统软件几十条街。今天我们就来掌握如何使用R语言优雅地计算超多变量(包括计算总分、计算平均值、缺失值处理、数值计数、重新编码、反向计分等)。

本文目录:

  1. 温故——传统软件的解决办法概览
  2. 知新——R语言和data.table包
  3. 进阶——自编R函数优雅计算多变量(附相关代码)

1 / 传统软件的解决办法概览

我们以经典的10题Rosenberg自尊量表(RSES)为例,这是一个4点Likert量表(1-4),其中有5题反向计分(第3、5、8、9、10题)。

如果用Excel来计算其总分或平均分,大家应该已经很熟悉了,可以分别用SUMAVERAGE函数:比如从A列~J列是RSES的10道题,那么在K2格输入“=AVERAGE(A2,B2,5-C2,D2,5-E2,F2,G2,5-H2,5-I2,5-J2)”,然后双击K2格右下角的黑色小十字,就自动填充算出了所有人的量表平均分。如果没有反向计分题,会简单很多,可以直接“=AVERAGE(A2:J2)”。想必这是大多数读者再熟悉不过的方法。

如果换做是SPSS,可能稍微复杂一点,比如原始变量名是RSES1、RSES2……RSES10,那么计算平均分可以先RECODE其中5道反向计分题并生成新变量再COMPUTE,也可以不RECODE直接COMPUTE(当然如果要计算信度,还是得先RECODE生成新变量):

COMPUTE RSES=MEAN(RSES1, RSES2, 5-RSES3, RSES4, 5-RSES5, RSES6, RSES7, 5-RSES8, 5-RSES9, 5-RSES10).
EXECUTE.

同样,在不涉及反向计分的情况下,SPSS的语句也能通过“to”(大小写不敏感)得到简化(但变量需要按顺序排好):

COMPUTE X=MEAN(X1 to X50).
EXECUTE.

如此看来,传统方法似乎还比较方便,所以这可能也是目前很多同学或老师不愿意学习使用R的原因:原来的软件已经够用、学编程需要花费比较多的成本、不想写代码、畏惧写代码……或者,学着学着就“从入门到放弃”了……

其实可以理解,毕竟我们有时候不太想跳出舒适区。

然而,随着变量增多,Excel和SPSS就会变得越来越不方便、越来越繁琐。

2 / R语言和data.table包

R语言会极大提高数据分析的效率,并且可以做几乎所有的统计分析。

自从两年前入坑R,我在一次次分析数据的过程中逐渐体会到R语言的美妙之处,无论是数据处理的简洁程度、统计功能的强大程度,还是作图的美观程度。虽说一个心理学研究者并不必要掌握太多编程语言(不可否认,问题比方法更重要,想法比技术更重要),但R绝对是一个巨大的宝库,经常会给我们很多惊喜,长远来看也会节省我们很多时间和精力。

在数据预处理方面,data.table作为data.frame的继承和升级版,不仅在处理大容量数据的时候速度更快,而且在拥有强大功能的同时代码设计却非常优雅简洁。官方速查手册请参考data.table (cheat sheet)。

86dc6a4fc1fcad6e6b2d3d4309adbedb.png
data.table简介

data.table的基本使用方式是“data[i, j, by]”(i为行,j为列,by为分组变量)。下面是一些例子:

require(data.table)
data=data.table(x=rep(1:2, each=3), y=1:6, z=6:1)
#    x y z
# 1: 1 1 6
# 2: 1 2 5
# 3: 1 3 4
# 4: 2 4 3
# 5: 2 5 2
# 6: 2 6 1# 筛选符合条件的行/个案
data[x==1 & y>1]
#    x y z
# 1: 1 2 5
# 2: 1 3 4# 筛选特定的列/变量
data[, c("y", "z")]
data[, .(y, z)]
#    y z
# 1: 1 6
# 2: 2 5
# 3: 3 4
# 4: 4 3
# 5: 5 2
# 6: 6 1# 同时筛选行和列
data[y %between% c(2, 4), "z"]
#    z
# 1: 5
# 2: 4
# 3: 3# 分组汇总
data[order(x), .(TotalN=.N, Ymean=mean(y), Zsd=sd(z), Zmax=max(z)), by=x]
#    x TotalN Ymean Zsd Zmax
# 1: 1      3     2   1    6
# 2: 2      3     5   1    3# 变量计算(“原地更新”,无需赋值给新变量)
data[, sum:=x+y+z]
#    x y z sum
# 1: 1 1 6   8
# 2: 1 2 5   8
# 3: 1 3 4   8
# 4: 2 4 3   9
# 5: 2 5 2   9
# 6: 2 6 1   9# 多变量同时计算(“:=”实则为data.table的一个特殊函数)
data[,":="(sum_xy=x+y,`y*z`=y*z)]
#    x y z sum sum_xy y*z
# 1: 1 1 6   8      2   6
# 2: 1 2 5   8      3  10
# 3: 1 3 4   8      4  12
# 4: 2 4 3   9      6  12
# 5: 2 5 2   9      7  10
# 6: 2 6 1   9      8   6# 数据匹配合并(即merge)
d1=data.table(x=letters[1:4], y=1:4)
#    x y
# 1: a 1
# 2: b 2
# 3: c 3
# 4: d 4
d2=data.table(x=letters[3:1], z=1:3)
#    x z
# 1: c 1
# 2: b 2
# 3: a 3
d2[d1, on="x"]  # 保留d1所有case
#    x  z y
# 1: a  3 1
# 2: b  2 2
# 3: c  1 3
# 4: d NA 4
d1[d2, on="x"]  # 保留d2所有case
#    x y z
# 1: c 3 1
# 2: b 2 2
# 3: a 1 3

通过上面这些简单的例子,大家对data.table应该已经有了基本的感受——非常简洁。事实上,如果要在data.frame实现相同的功能,还需要用到许多其他的函数和包(例如which、aggregate、merge,多变量计算则需要用到dplyr包的mutate等等),而在data.table里面,一切都变得非常优雅。

然而,优雅才刚刚开始。

3 / 自编R函数优雅计算多变量

虽然data.table提供了“:=”函数使得多变量计算容易很多,但现实情况往往比较复杂,尤其是本文开头所说的“超多变量”情况。颇为遗憾的是,data.table本身并没有提供特别有效的函数来“优雅地”进行“超多变量”的计算。

我们不妨先创建一个案例数据,用来模拟纷繁复杂的现实情况,这里我刻意把“x2”和“x4”的位置倒了过来,并且加了几个缺失值NA:

d=data.table(x1=1:5, x4=c(2,2,5,4,5), x3=c(3,2,NA,NA,5), x2=c(4,4,NA,4,5), x5=c(5,4,3,4,5))
#    x1 x4 x3 x2 x5
# 1:  1  2  3  4  5
# 2:  2  2  2  4  4
# 3:  3  5 NA NA  3
# 4:  4  4 NA  4  4
# 5:  5  5  5  5  5# 如果要计算x1-x5的平均值:
# (以下均为错误代码!)
d[,":="(X=mean(x1, x2, x3, x4, x5))]  # 报错
d[,":="(X=mean(c(x1, x2, x3, x4, x5)))]  # 依然不对,返回值都是NA
d[,":="(X=mean(c(x1, x2, x3, x4, x5), na.rm=TRUE))]  # 还是不对,返回值都是同一个数字
d[,":="(X=(x1+x2+x3+x4+x5)/5)]  # 回到了最笨的办法,但缺失值依然无法处理

可以看到,如果我们想计算x1-x5的平均值,想想容易,真正实现起来却处处碰壁。其实要想实现简便的变量计算,需要用到很多特别的函数,比如mapply、eval,有的地方还需要用到正则表达式。

但不用担心,我已经针对几个常用的变量计算需求编好了相应的R函数。由于具体思路比较复杂,这里不详细展示源代码,大家可以从我的GitHub下载这些函数的源代码并调用(BruceFunctions.R)。

# 或者在线调用BruceFunctions.R
source("https://raw.githubusercontent.com/psychbruce/stats/master/BruceFunctions.R")

自编函数包括:

COUNT:统计每个被试的不同变量(题目)中某个值出现的个数SUM:简便计算多个变量(题目)的总分MEAN:简便计算多个变量(题目)的平均分STD:简便计算多个变量(题目)的标准差CONSEC:统计多个变量(题目)中连续相同数字出现最多的个数……

主要的参数包括:

data:原数据var & item:需计算的变量及其序号(同时定义),例如var="RSES", item=1:10;如果变量的原始顺序是乱序,则变量会以1-10的顺序重新排列;此为推荐用法,可省略参数名vars:直接规定使用哪些变量,例如vars=c("x1", "x2");不可省略该参数名varrange:原数据中某段范围的变量(原始顺序),例如varrange="x1:x5";不可省略该参数名
(以上三种变量界定方式只需选择其中一种即可,当然函数在实际运行时会把不同情况统一转换为vars)rev:反向计分题有哪些,可以是单个数字(与item参数的顺序对应),可以是具体的变量名,也可以是数字/变量名组成的向量likert:如果有反向计分题,则需要同时定义Likert是几点量表,可以是c(1, 7)的形式,也可以是1:7的形式na.rm:是否跳过缺失值,默认为TRUE(适用大多数情况),一般不用再做设置

下面是具体用法:

d[,":="(n_na=COUNT(d, "x", 1:5, value=NA),  # 统计x1-x5中缺失值的个数n_2=COUNT(d, "x", 1:5, value=2),  # 统计2的个数sum=SUM(d, "x", 1:5),  # 计算x1-x5的总分(缺失值跳过)mean1=MEAN(d, "x", 1:5),  # 计算x1-x5的平均分(缺失值跳过)mean2=MEAN(d, vars=c("x1", "x4")),  # 只计算x1和x4的平均分mean3=MEAN(d, varrange=c("x1", "x2")),  # 计算从x1到x2的平均分(实际有4个变量)mean4=MEAN(d, varrange="x1:x2", rev="x2", likert=1:5),  # 同上,但规定x2为反向计分题sd=STD(d, "x", 1:5, rev=c(2, 5), likert=1:5),  # 计算x1-x5的标准差,规定x2和x5为反向计分题cons1=CONSEC(d, "x", 1:5),  # 统计x1-x5连续相同数字出现最多的个数(变量按照1-5重新排列)cons2=CONSEC(d, varrange="x1:x5"))]  # 同上,但以变量原始顺序排列#    x1 x4 x3 x2 x5 n_na n_2 sum    mean1 mean2 mean3    mean4       sd cons1 cons2
# 1:  1  2  3  4  5    0   1  15 3.000000   1.5   2.5 2.000000 0.836660     0     0
# 2:  2  2  2  4  4    0   3  14 2.800000   2.0   2.5 2.000000 0.000000     2     3
# 3:  3  5 NA NA  3    2   0  11 3.666667   4.0   4.0 4.000000 1.154701     0     0
# 4:  4  4 NA  4  4    1   0  16 4.000000   4.0   4.0 3.333333 1.154701     2     2
# 5:  5  5  5  5  5    0   0  25 5.000000   5.0   5.0 4.000000 2.190890     5     4

另外,还有两个函数是在已有包的基础上进行的简单扩展(所谓“站在巨人的肩膀上”):

RECODE:变量转换/重新赋值,功能同SPSS的RECODE;该函数是直接调用了car包的recode函数
# RECODE用法示例
data[, BirthGroup:=RECODE(BirthYear, "lo:1989=1; 1990:1999=2; 2000:2009=3; 2010:hi=4; else=NA")]
Alpha:更方便地计算内部一致性信度,不需要对反向计分题额外生成新变量;该函数是调用了jmv包的reliability函数(jmv其实是jamovi软件的程序包),并做了必要的参数设置和参数扩展
(输出结果为三线表,指标包括5个——量表平均分、量表标准差、量表α系数、校正后的题总相关 [即item-rest correlation]、该题如果删除后的量表α系数,以及会智能输出一些Note)

最后仍然以RSES自尊量表为例,演示上述函数的用法:

# 计算平均分(数据“原地更新”)
data[, ":="(RSES=MEAN(data, "RSES", 1:10, rev=c(3, 5, 8, 9, 10), likert=1:4))]# 计算Cronbach's α系数
Alpha(data, "RSES", 1:10, rev=c(3, 5, 8, 9, 10))

e429d80062ed10af265390e55f06af0e.png
Alpha函数输出结果样例(基于jamovi的jmv包)

结语

面对“多变量计算”问题,虽然Excel和SPSS也能解决,但局限较多、过程繁琐。而基于data.table和自编函数,我们既可以很方便地用少量代码计算量表总分、量表平均分,也能在不生成新变量的情况下直接进行反向计分的处理和量表信度的计算,而且基本上所有的单个功能都只需要短短一行代码就能搞定。大道至简。

再啰(ān)嗦(lì)几句

  • 用R千万别用R本身(我一般只用R本身当计算器),RStudio才是写代码必需的IDE(IDE = 集成开发环境)
  • jamovi作为一款基于R的新兴统计软件,具有比SPSS更简洁美观的界面设计,同时又拥有更强大丰富的统计功能,未来几年应该会大范围取代SPSS,和R一起占领统计市场(jamovi的一个新出的module甚至已经能做多重中介和有调节的中介了)
  • 简单数据用jamovi、复杂数据用R——可以说是一种新的标配
  • 到底有多好,谁用谁知道!

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

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

相关文章

php模板初级教程,风格模板初级不完全修改教程

风格模板初级不完全修改教程更新时间:2006年10月09日 00:00:00 作者:就自己的一点点经验,希望能给初接触模版修改的朋友有个参考。关于模版修改, 引用星星签名里的一句话“学好HTML很重要” :)一个风格,…

语音对讲软件_微信语音转播软件是哪个?怎样一键转发?

文末送社群运营资料有一句话说得好,好马配好鞍,如果经验丰富的社群工作人员想要看到良好的社群运营效果,那单单凭借个人的力量是远远不够的,建议将希望寄托在第三方工具的身上,比如微信语音转播软件就是绝佳选择。按照…

php if require,关于php:required_if Laravel 5验证

我有一个表格,用户可以填写出售房屋的信息。 对于其中一项投入,用户必须选择"待售"或"待租"天气。 如果是For Sale,则会出现两个价格输入字段,如果是For Rent,则会基于jQuery显示一些其他价格输入…

asp.net 安装element ui_不用上官网,自己部署一套Element官方最新文档

ElementUI官方的访问速度一直很慢,公司内网也无法进行外网访问。故研究了下最新的ElementUI API(2.13.2)部署教程。先上效果图ElementUI文档部署过程到github下载最新的elementui源码,这里我使用git下载到本地git clone https://github.com/ElemeFE/elem…

如何写一个计算器?

考虑这样一个问题,给定一个字符串,“11(34)-2*38/2”,如何将它转化为如下形式: “112” “347” “279” “2*36” “9-63” “8/24” “347” 换句话说,就是如何将字符串按照四则运算计算出来,如何写一个计…

由于在客户端检测到一个协议错误_HTTP协议,你了解多少?

HTTP简介HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。HTTP是一个属于应用层的面向对象的协议&am…

idea中没有j2ee_idea神器功能大全

IDEA 全称 IntelliJ IDEA,是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手、代码自动提示、重构、J2EE支持、各类版本工具(git、svn、github等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面…

linux 固定ip_linux固定IP

在新安装的Linux系统命令行下,敲入:ifconfig,显示如下界面。上面这张图显示网卡没有启动,那么我们敲入代码:ifup eth0启动网卡。网卡启动后,我们可以看出,IP地址和网关等其他信息都已经出现。但是我们需要的…

php编译称opcode文件,PHP源码保护和性能加速

什么是Opcache?每一次执行 PHP 脚本的时候,该脚本都需要被编译成字节码,而 Opcache 可以对该字节码进行缓存,这样,下次请求同一个脚本的时候,该脚本就不需要重新编译,这极大节省了脚本的执行时间&#xff…

9553下载站java,java se development kit11最新版 64位

java se development kit11,简称java11,是一款专门进行java开发的编程软件,这款软件还拥有applet和组件的开发环境等操作,是程序员们进行java开发的飞铲不错软件,如果你喜欢这款软件,那就来下载基本介绍自从…

java sleep方法_一文搞懂 Java 线程中断!

在之前的一文《如何”优雅”地终止一个线程》详细说明了 stop 终止线程的坏处及如何优雅地终止线程,那么还有别的可以终止线程的方法吗?答案是肯定的,它就是我们今天要分享的——线程中断。下面的这断代码大家应该再熟悉不过了,线…

java 观察者模式_图解Java设计模式之观察者模式

图解Java设计模式之观察者模式天气预报项目需求天气预报设计方案 1 - 普通方案观察者模式(Observer)原理观察者模式解决天气预报需求观察者模式在JDK应用的源码分析天气预报项目需求1)气象站可以将每天测量到的湿度、温度、气压等等以公告的形…

怎么在同一页中分页_分库分表业界难题,跨库分页的几种常见方案

为什么需要研究跨库分页?互联网很多业务都有分页拉取数据的需求,例如:(1)微信消息过多时,拉取第N页消息;(2)京东下单过多时,拉取第N页订单;(3)浏览58同城,查看第N页帖子;…

content add tpl.php,phpcms后台批量上传添加图片文章方法详解(一)

注:以下所有代码中,红色部分为增加部分。一、在后台增加批量添加按钮打开“phpcms\modules\content\templates\content_list.tpl.php”文件搜索“$category[‘catname‘]));?>”在这句话的后天的添加:a echo"" href":;&q…

sap 供应商表_财务人员学习SAP的路线图

有许多网友在公众号给我们留言,咨询财务人员学习SAP的事情,如何才能快速掌握SAP,有没有捷径什么的。今天就给大家分享一下财务人员学习SAP的经验,希望能够为财务人员揭开SAP神秘的面纱,学习SAP少走弯路。刚接触SAP的财…

nodejs搭配phantomjs highcharts后台生成图表

简单分享一下,后台使用nodejs结合highcharts、phantomjs生成报表图片的方法。这主要应用在日报邮件。 主要参考以下资料: http://www.highcharts.com/component/content/article/2-news/52-serverside-generated-charts#phantom_usagehttps://bitbucket.…

vue 页面切换动画_Flutter Hero动画让你的APP页面切换充满动效 不一样的体验 不一样的细节处理...

优美的应用体验 来自于细节的处理,更源自于码农的自我要求与努力,当然也需要码农年轻灵活的思维。本文章实现的Demo效果,如下图所示:class HeroHomePage extends StatefulWidget { override _TestPageState createState() > …

自定义左右侧滑菜单

实现效果: 左右侧滑菜单,侧滑栏占主屏比为60%监听触控,自定义滑动动画,当侧边栏滑动超过50%松开触控将自动滑动到60%,未超过50%松开触控回归侧边栏隐藏为主屏设置蒙版效果,根据侧滑菜单的占屏比设置主屏蒙版…

ubuntu php7 memcache,linux上安装php7 memcache扩展

php7安装memcache扩展需要memcache php7的分支 否则安装会失败php7的memcache扩展安装,真的很让人心碎!下面则是php7的扩展memcache安装了。用之前的php版本安装是没有问题,但是用了php7安装 http://pecl.php.net/package/memcache 下的任一…

好文推荐系列--------(3)GruntJS 在线重载 提升生产率至新境界

好文原文地址:http://segmentfault.com/a/1190000000354555 本文将首先介绍grunt-markdown插件如何配合HTML模板使用,接着我将介绍如何使用grunt-watch插件将工作效率提升至新层次。如果你不熟悉GruntJS,请先阅读我关于GruntJS的文章。 Githu…