提取组中第一次出现变量的行

时间:2016-11-01 21:23:12

标签: r

我有一个庞大的数据集(100多个变量超过200万行;下面是一个小样本)。对于每个subj_trial组,我想找到包含在" .wav"中的每个唯一变量的第一个匹配项。在message。它应该只包含,而不是结束(即* .wav),因为某些行在message字段中有一堆信息(示例中没有图示,抱歉)。

输出只有这三列的data.frame是可以的,但不是必需的。我稍后需要使用timestamp列进行分析。

我发现了这个问题:Extract rows for the first occurrence of a variable in a data frame,但对于我的生活,我无法用这个例子来适应我的。

以下是一些示例数据:

   subj_trial     message timestamp
1         1_1 message 459    755616
2         1_1           .    755618
3         1_1   test1.wav    755662
4         1_1           .    765712
5         1_1   test1.wav    767918
6         1_2           .    769342
7         1_2   test2.wav    775662
8         1_2           .    786412
9         1_2   test2.wav    797460
10        1_2           .    807626
11        1_3   test3.wav    817794
12        1_3  warning 11    827960
13        2_1 message 481    817313
14        2_1   test1.wav    817347
15        2_1           .    834959
16        2_1   test1.wav    855007
17        2_1           .    880107
18        2_2           .    895723
19        2_2   test2.wav    922671
20        2_2           .    958003
21        2_2   test2.wav    994385
22        2_3           .   1016217
23        2_3   test3.wav   1036899
24        2_3           .   1047331
25        2_3   test3.wav   1142527

这是我在这里处理的一个非常小的例子。对于每个subj_trial组,可能有3000行,并且有超过700个组。

这是我想要拥有的一个例子。

  subj_trial   message timestamp
1        1_1 test1.wav    755662
2        1_2 test2.wav    775662
3        1_3 test3.wav    817794
4        2_1 test1.wav    817347
5        2_2 test2.wav    922671
6        2_3 test3.wav   1036899

通过这样做,我已经弄明白了如何在整个数据集中获取message中的唯一值:

unique_message <- df[match(unique(df$message), df$message),]

但是我无法弄清楚如何按小组来做。我也尝试在group_by包中使用dplyr,但也无法使用window.location.href = '/yourpage'。朋友,请怜悯和指路。谢谢!

3 个答案:

答案 0 :(得分:2)

同样使用data.table,但使用更简洁的表述:

setDT(DT)
DT[,.SD[grep("\\.wav",message)[1]],by=subj_trial]

修改:根据以下评论的建议,

DT[grepl("\\.wav", message), .SD[1], by=subj_trial]

可能更快,因为它使用布尔逻辑和优化的I子集。

  

.SD是一个data.table,包含每个组的DT数据子集,不包括by(或keyby)中使用的任何列。

     

by有点像SQL中的group by运算符。它指定分组列。

     

grep(pattern, x)返回patternx的所有匹配项的索引,其中x是向量。 \\之前的.wav会阻止grep将.视为特殊字符(在grep的解析中,未转义的.表示'任何')。

     

vector_name[1]返回名为vector_name的向量的第一个元素。它可以在函数的结果上调用,例如上面的grep。

     

data.table公式为DT[I,J,by] - I是子集或联接,J是要执行的操作,by是分组元素。在我们的例子中,I被忽略(因此领先,)因为我们想要处理整个集合。 J是所有.SD列的操作。 by是您希望结果分组的列。

答案 1 :(得分:1)

使用$("#email").on('submit', function(e){ e.preventDefault(); var input = $(this).val(); var match = input.match(/^\w+@atlanticbay.com$/i); if(typeof match != 'null'){ console.log("we are good"); // add submit codes here..probably ajax } console.log("prevented"); });

data.table

答案 2 :(得分:1)

如果您有兴趣,这里还有一个dplyr解决方案:

dat %>%
  filter(grepl("\\.wav", message)) %>%
  group_by(subj_trial) %>%
  top_n(n=1, wt=desc(timestamp))

首先,将数据过滤到消息列中包含* .wav的数据。然后按主题试验对数据进行分组,并返回具有最小时间戳的最高结果。这假设您需要最小时间戳,而不一定是数据集中的第一个时间戳(即,如果首先出现时间戳较大的记录,则不会返回)。我不清楚你在寻找什么,但也许在你的情况下没有区别。

由于我总是对data.tabledplyr方法之间的效率差异感到好奇,所以我做了microbenchmark测试。看起来在这种情况下,data.table具有轻微的速度优势:

library(microbenchmark)
library(data.table)

set.seed(1)
dat <- data.frame(subj_trial=paste0(sample(1:20,1e6,replace=TRUE),"_",sample(1:20,1e6,replace=TRUE)),
                  message=sample(c(".wav","others"), 1e6, replace=TRUE),
                  timestamp=round(seq(from=1000, to=9142527, length.out = 1e6))) 

dat2 <- dat
setDT(dat2)

microbenchmark({dat %>%
  filter(grepl("\\.wav", message)) %>%
  group_by(subj_trial) %>%
  top_n(1, wt=desc(timestamp))},
  {dat2[grepl("\\.wav", message), .SD[1], by=subj_trial]})

结果:

Unit: milliseconds

expr

dat %>% filter(grepl("\\\\.wav", message)) %>% group_by(subj_trial) %>% top_n(1, wt = desc(timestamp))
dat2[grepl("\\\\.wav", message), .SD[1], by = subj_trial] 
      min       lq     mean   median       uq      max neval cld
 332.9693 357.7426 387.2245 367.6443 380.9935 637.9223   100   b
 263.0292 272.8627 293.4976 281.4568 285.7699 582.9954   100  a