3

我正在尝试识别纵向数据集中的最后一个letterID

假设我的数据看起来像这样,

dfL <- data.frame(ID = c(1L, 1L, 1L, 4L, 4L, 4L, 4L, 4L, 9L, 9L, 9L, 9L, 9L, 10L), week = c("BS", 4L, 6L, "BS", 6L, 9L, 9L, 12L, "BS", 4L, 6L, 9L, 12L, "BS"), outcome = c(14L, 28L, 42L, 14L, 46L, 64L, 71L, 85L, 14L, 28L, 51L, 66L, 84L, 0L), letter = c("a", "b", "a", "b", "a", "b", "a", "b", "a", "b", "a", "b", NA, NA)); dfL

每个ID都有 s 串字母(ab's),我需要找到其中的最后一个字母ID并将放在基线上。

   ID week outcome letter
1   1   BS      14      a
2   1    4      28      b
3   1    6      42      a
4   4   BS      14      b
5   4    6      46      a
6   4    9      64      b
7   4    9      71      a
8   4   12      85      b
9   9   BS      14      a
10  9    4      28      b
11  9    6      51      a
12  9    9      66      b
13  9   12      84   <NA>
14 10   BS       0   <NA>

我想最终的结果会是这样的,

   ID week outcome letter last_letter
1   1   BS      14      a      a
2   1    4      28      b   <NA>
3   1    6      42      a   <NA>
4   4   BS      14      b      b
5   4    6      46      a   <NA>   
6   4    9      64      b   <NA>
7   4    9      71      a   <NA>
8   4   12      85      b   <NA>
9   9   BS      14      a      b
10  9    4      28      b   <NA>
11  9    6      51      a   <NA>
12  9    9      66      b   <NA>
13  9   12      84   <NA>   <NA>
14 10   BS       0   <NA>   <NA>

我已经摆弄了which.maxfrom the data.tablepackage 和 with ave,但我还是有点卡住了。

4

3 回答 3

4

使用 base R'save我会用这样的自定义函数来处理它:

FUN <- function(x) {
    if (all(is.na(x))) return(NA)
    tail(na.omit(x), 1)
}

dfL$lastL <- with(dfL, ave(letter, ID, FUN=FUN))

##    ID week outcome letter lastL
## 1   1   BS      14      a     a
## 2   1    4      28      b     a
## 3   1    6      42      a     a
## 4   4   BS      14      b     b
## 5   4    6      46      a     b
## 6   4    9      64      b     b
## 7   4    9      71      a     b
## 8   4   12      85      b     b
## 9   9   BS      14      a     b
## 10  9    4      28      b     b
## 11  9    6      51      a     b
## 12  9    9      66      b     b
## 13  9   12      84   <NA>     b
## 14 10   BS       0   <NA>  <NA>

编辑:

如果您希望它看起来像您的,<NA>那么这种方法tapply将起作用。

FUN <- function(x) {
    if (all(is.na(x))) {
        first <- NA
    } else {
        first <- tail(na.omit(x), 1)
    }
    out <- as.character(rep(NA, length(x)))
    out[1] <- as.character(first)
    out
}

dfL$lastL <- factor(unlist(with(dfL, tapply(letter, ID, FUN=FUN))))

##    ID week outcome letter lastL
## 1   1   BS      14      a     a
## 2   1    4      28      b  <NA>
## 3   1    6      42      a  <NA>
## 4   4   BS      14      b     b
## 5   4    6      46      a  <NA>
## 6   4    9      64      b  <NA>
## 7   4    9      71      a  <NA>
## 8   4   12      85      b  <NA>
## 9   9   BS      14      a     b
## 10  9    4      28      b  <NA>
## 11  9    6      51      a  <NA>
## 12  9    9      66      b  <NA>
## 13  9   12      84   <NA>  <NA>
## 14 10   BS       0   <NA>  <NA>
于 2013-03-27T18:58:19.700 回答
2

我希望我的问题是正确的(我真的不知道每个 ID 的最后一个字母是什么;我会假设它是结果最高的那个):

然后是一个data.table解决方案:

library(data.table)
dfL <- as.data.table(dfL)
setkey(dfL, ID, outcome)
intDT <- dfL[!is.na(letter), list(lastL = tail(letter, 1)), by=ID]
setkey(intDT, ID)
intDT[dfL]
    ID lastL week outcome letter
 1:  1     a   BS      14      a
 2:  1     a    4      28      b
 3:  1     a    6      42      a
 4:  4     b   BS      14      b
 5:  4     b    6      46      a
 6:  4     b    9      64      b
 7:  4     b    9      71      a
 8:  4     b   12      85      b
 9:  9     b   BS      14      a
10:  9     b    4      28      b
11:  9     b    6      51      a
12:  9     b    9      66      b
13:  9     b   12      84     NA
14: 10    NA   BS       0     NA

只是对我在这里所做的事情的简短解释:我dfL首先进行排序,然后为每个 ID ( by=ID) 获取最后一个值letter(使用 function 完成tail)。之后,我必须再次合并这两个 data.tables。

更容易(感谢 Luciano 的评论):

dfL[!is.na(letter), lastL := tail(as.character(letter), 1), by=ID]
    ID week outcome letter lastL
 1:  1   BS      14      a     a
 2:  1    4      28      b     a
 3:  1    6      42      a     a
 4:  4   BS      14      b     b
 5:  4    6      46      a     b
 6:  4    9      64      b     b
 7:  4    9      71      a     b
 8:  4   12      85      b     b
 9:  9   BS      14      a     b
10:  9    4      28      b     b
11:  9    6      51      a     b
12:  9    9      66      b     b
13:  9   12      84     NA    NA
14: 10   BS       0     NA    NA

在这里,这一切都是一步完成的。但是,这仅在将列转换letter为字符时才有效。

于 2013-03-27T18:54:19.883 回答
2

这是使用 plyr 的一种方法:首先省略 NA,按 id 拆分并查看最后一个值。然后合并回来。

library(plyr)

last_letter <- ddply(na.omit(dfL), .(ID), function(x) tail(as.character(x$letter),1))
last_letter$week <- "BS"
names(last_letter)[2] <- "last_letter"
merge(dfL, last_letter, by = c("ID", "week"), all=TRUE)

   ID week outcome letter last_letter
1   1    4      28      b        <NA>
2   1    6      42      a        <NA>
3   1   BS      14      a           a
4   4   12      85      b        <NA>
5   4    6      46      a        <NA>
6   4    9      64      b        <NA>
7   4    9      71      a        <NA>
8   4   BS      14      b           b
9   9   12      84   <NA>        <NA>
10  9    4      28      b        <NA>
11  9    6      51      a        <NA>
12  9    9      66      b        <NA>
13  9   BS      14      a           b
14 10   BS       0   <NA>        <NA>
于 2013-03-27T18:59:07.370 回答