微信号:gh_a9d9c3cb1ca5

介绍:市面上的教材太水?学了半天还是不知道如何处理工作中的数据?大猫的R语言课堂每期都和你分享一个工作研究中的实际问题,期期干货,就是这么实在!

R Tricks: 如何巧为观测标记序号

2016-07-27 22:20 大猫
在前面
本期大猫课堂将会开始一个新的系列:你不知道的R Tricks。这个系列将搬运stackoverflow.com(以后简称SO)上关于R数据处理的一些经典问答。大猫除了翻译原文,还会从初学者的角度为代码补充详细的解释。其实这些问题基本上都是大猫自己在数据处理过程中实际遇到的,看了SO上的答案不禁拍案叫绝,忍不住和大家分享。

第一期的主题是:如何巧为观测标记序号?这个问题在事件研究法时经常会遇到,但仅看标题小伙伴们是不是还觉得云里雾里?快点往下看吧!

出问题
话说有个小伙伴在StackOverflow上提出了这样一个问题:假设我现在有这样一个数据集:
建立样例数据集的代码:
▶ set.seed(42)
▶ dt <- data.table(group = sample(0:1, 10000, rep = TRUE),  n = 0L)
其中,group的取值只能是0和1, 表示一件事情是否发生。你可以把group理解为一个人是否去健身房,如果连续出现1则意味着那几天每天都去,出现0则说明那人偷懒了。现在的问题是,我希望为每个连续的0或者1编号。例如连续出现3个0, 那么n就标记为1、2、3,如果后面接了一个1, 那么就重新从1开始标记。也即最终的结果应该是:
可以看到,group每变动一回,n就重新计数一次。那么这个代码究竟该怎么写呢?其实只需要一行就够啦!

原问题大家可以访问以下链接:http://stackoverflow.com/questions/25415749/creating-a-sequence-in-a-data-table-depending-on-a-column

决问题
在解决本问题的过程中我们需要用到data.table包!

虽然最终版本的代码只需要一行,但在这里大猫将会把它拆解为三部分:

首先,我们需要有一个变量能标记出group的变化。也就是当group不变时取0,变化时取1。在R中,求差分的函数diff非常适合完成这个任务。它可以计算当前观测和上一行观测相比变化了多少。我们试着用一下:
▶ dt[, diff := c(0, diff(group))]
结果如下:
看,现在每当group发生变化,diff就非零,但是diff只能在0、-1、1中变动,并不能把每次变化都用1、2、3……的数字给标记出来。那如何能够把每次变化都累加起来呢?这时就需要cumsum累加函数:
▶ dt[, cumsum := cumsum(abs(diff))]
结果如下:
看,diff每变化一次,cumsum就把这种变化累加起来了(注意我们用到了abs绝对值函数)。目前为止,我们已经成功把每次变化都分组并加以标号(见cumsum变量),看起来是不是几乎大功告成了?最后一步,我们只需要在每个by=cumsum组中将观测从1开始标号即可:
▶ dt[, n := seq(.N), by = cumsum]
最终结果为:
注意,我们这里用cumsum的值进行了分组,并且用了seq(.N)这个语句。".N"表示当前by组有多少的观测,而seq(.N)则产生从1至.N的一个整数序列。

例如,对于上面的第一行和第二行观测来说,他们同属于cumsum=0这组。因为这组一共只有两行,所以.N=2,而seq(.N)就产生{1, 2}这样一个整数序列,并最终赋值给n。

如果把上面三步写成一行代码就是这个样子:

▶ dt[, n := seq(.N), by = list(cumsum(c(0, abs(diff(group)))))]

期总结
本期大猫带领大家学习了一个为分组观测进行编号的小技巧。还记得在开篇大猫说这个技巧在事件研究法中特别实用吗?因为在事件研法中,我们一般会给事件日标为1,非事件日标为0,对于每个事件之间的一段时间,我们往往希望能够用1开始为其标号,这对于后续统计相当有用。此外,在做一些游程检验的过程中,这个技巧也非常管用。

我是大猫,咱们下期见!
 
大猫的R语言课堂

我是 大猫,我是一个高中读文科但却在代码、数学的路上狂奔不止的Finance Ph. D Candidate。

我的微信号是iRoss2007

我的 R语言课堂关注R语言、数据挖掘以及经济金融学。

我与大家分享我的知识,我相信独乐乐不如众乐乐

我还有许多 好玩的计划。

更多的精彩内容正在路上。
长按二维码关注
 
大猫的R语言课堂 更多文章 高效R开发(二):Microsoft R R Tricks: 如何处理Gaps &amp; Islands问题? R Tricks: 如何巧为观测标记序号 高效R开发(二):Microsoft R R开发环境:如何做到既酷炫又高效?(一)
猜您喜欢 其实除了爱妻爱女爱事业,扎克伯格还有一个很牛的技能 | 书单 自我改造计划:身体 读写文件与读写数据库的效率比较 【840】解密“攻城狮使用手册” TW洞见|敏捷咨询日记—匠人精神