【问题标题】:Creating last observation flags for grouped data with dplyr使用 dplyr 为分组数据创建最后观察标志
【发布时间】:2015-11-29 08:11:05
【问题描述】:

我搜索并找到了许多接近但不能完全回答我的问题的解决方案。

我想要一个将 0/1 标志添加到数据的函数,表示每单位的最后一次观察。数据按单元和已完成的测试类型分组。

我想使用 dplyr 并进行以下尝试,但是第二次 mutate_ 调用是错误的。

getLastObsFlag <- function(data, id="subject", time="studyday", test="test"){
  data <- arrange_(data, id, test, time) %>%
    mutate_(lastObsFlag = 0) %>%
    group_by_(id, test) %>%
    mutate_(lastObsFlag = replace(time, n(), 1))

  as.data.frame(data)
}

# Restructure pbcseq from the survival package
junk <- gather(pbcseq, test, value, 12:18)
# That just loaded reshape2 and plyr, so unload them
unloadNamespace("reshape2")
unloadNamespace("plyr")
getLastObsFlag(junk, id="id", time="day", test="test")

n() 的调用会引发错误:Error in dplyr::n() : This function should not be called directly

我已经读过这是一个连接 plyr 和 dplyr 的问题(我希望使用 dplyr::n() 来克服这个问题)。我查了一下,plyr 是loaded via a namespace (and not attached)。我使用 unloadNamespace 将其删除(并 reshape2),但仍然收到相同的错误消息。

如有任何指示,我将不胜感激。我没有加入n(),因此可以使用替代解决方案。

R version 3.2.2 (2015-08-14)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 14.04.3 LTS

locale:
 [1] LC_CTYPE=en_GB.UTF-8       LC_NUMERIC=C               LC_TIME=en_GB.UTF-8        LC_COLLATE=en_GB.UTF-8     LC_MONETARY=en_GB.UTF-8   
 [6] LC_MESSAGES=en_GB.UTF-8    LC_PAPER=en_GB.UTF-8       LC_NAME=C                  LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] parallel  splines   stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] dmhelp_0.5         brglm_0.5-9        profileModel_0.5-9 dplyr_0.4.3        tidyr_0.2.0        gbm_2.1.1          lattice_0.20-33   
[8] survival_2.38-3   

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.0     assertthat_0.1  MASS_7.3-44     grid_3.2.2      R6_2.1.1        DBI_0.3.1       magrittr_1.5    stringi_0.5-5  
 [9] lazyeval_0.1.10 tools_3.2.2     stringr_1.0.0  

【问题讨论】:

  • 我刚刚尝试了一些我认为您建议的变体,但得到了相同的错误消息(plyr 仍未附加或加载)。请澄清
  • 你可以试试下面发布的解决方案吗?

标签: r dplyr


【解决方案1】:

我们可以从library(lazyeval) 使用interp

library(lazyeval)
getLastObsFlag <- function(data, id="subject", time="studyday", test="test"){
       data <- arrange_(data, id, test, time) %>%
                    mutate_(lastObsFlag = 0) %>%
                    group_by_(id, test) %>%
                    mutate_(.dots=list(lastObsFlag = interp(~replace(lastObsFlag,
                                               n(), 1))))
      as.data.frame(data)
   }

测试后

head(getLastObsFlag(junk, id="id", time="day", test="test"),25)[c('id', 'test', 'lastObsFlag')]
#  id     test lastObsFlag
#1   1     bili           0
#2   1     bili           1
#3   1     chol           0
#4   1     chol           1
#5   1  albumin           0
#6   1  albumin           1
#7   1 alk.phos           0
#8   1 alk.phos           1
#9   1      ast           0
#10  1      ast           1
#11  1 platelet           0
#12  1 platelet           1
#13  1  protime           0
#14  1  protime           1
#15  2     bili           0
#16  2     bili           0
#17  2     bili           0
#18  2     bili           0
#19  2     bili           0
#20  2     bili           0
#21  2     bili           0
#22  2     bili           0
#23  2     bili           1
#24  2     chol           0
#25  2     chol           0

【讨论】:

  • 不完全...当我们到达第二个病人head(getLastObsFlag(junk, id="id", time="day"), 25)
  • 谢谢,没有正确检查。让我再检查一下数据。
  • @harrys 我认为您的功能存在缺陷。您仅将“时间”的最后一次观察替换为 1。相反,我认为您希望将 lastObsFlag 替换为 1。
  • @harrys 我更新了帖子。你能检查一下这是否是你想要的。
  • 谢谢!我所做的唯一更改是致电lazyeval::interp。非常感谢
【解决方案2】:

我们可以使用ifelsedplyrwindow 函数在mutate 中添加一个变量到整个数据框。

junk &lt;- junk %&gt;% group_by(id) %&gt;% arrange(day) %&gt;% mutate(flag = ifelse(min_rank(desc(day))!=1,0,1))

测试结果...

 id futime status trt      age sex day ascites hepato spiders edema stage     test   value flag
1   1    400      2   1 58.76523   f   0       1      1       1     1     4     bili   14.50    0
2   1    400      2   1 58.76523   f   0       1      1       1     1     4     chol  261.00    0
3   1    400      2   1 58.76523   f   0       1      1       1     1     4  albumin    2.60    0
4   1    400      2   1 58.76523   f   0       1      1       1     1     4 alk.phos 1718.00    0
5   1    400      2   1 58.76523   f   0       1      1       1     1     4      ast  138.00    0
6   1    400      2   1 58.76523   f   0       1      1       1     1     4 platelet  190.00    0
7   1    400      2   1 58.76523   f   0       1      1       1     1     4  protime   12.20    0
8   1    400      2   1 58.76523   f 192       1      1       1     1     4     bili   21.30    1
9   1    400      2   1 58.76523   f 192       1      1       1     1     4     chol      NA    1
10  1    400      2   1 58.76523   f 192       1      1       1     1     4  albumin    2.94    1

【讨论】:

  • 我觉得这应该更容易——只需使用mutate(lastObsFlag=(row_number() == n()))。 (标志显示为布尔值,在我看来这比 0/1 更可取)。
  • 当我将它包装在一个具有 2 级分组(id 和 test)的函数中时,它返回错误的东西,我还不明白为什么......
  • 我在您的函数和附加分组中测试了我的答案。它按预期工作,但前提是我使用 nse dplyr 方法(mutate 而不是mutate_)。当使用mutate_ eval 方法时,我得到每个lastObsFlag = 1,不管是哪一天。我也不知道为什么。
猜你喜欢
  • 1970-01-01
  • 2020-12-21
  • 2014-08-26
  • 2019-02-25
  • 2019-06-04
  • 2019-05-28
  • 2021-04-26
  • 2011-10-21
  • 1970-01-01
相关资源
最近更新 更多