我正在尝试在R中找到一种正确的方法来查找重复值,并将值1添加到按ID分组的每个后续重复值中。例如:
data=data.table(id=c('1','1','1','1','1','2','2','2'),value=c(95,100,101,101,101,20,35,38))
data$new_value <- ifelse(data[,data$value] == lag(data$value,1), lag(data$value,1)+1 ,data$value)
data$desired_value <- c(95,100,101,102,103,20,35,38)
制作:
id value new_value desired_value
1: 1 95 NA 95
2: 1 100 100 100
3: 1 101 101 101
4: 1 101 102 102
5: 1 101 102 103
6: 2 20 20 20
7: 2 35 35 35
8: 2 38 38 38
我尝试使用ifelse执行此操作,但它不能递归地工作,因此它仅适用于以下行,而不适用于任何后续行。此外,lag
函数会导致我失去value
中的第一个值。
我见过包含make.names
或make.unique
字符变量的示例,但无法找到重复数值的解决方案。
背景:我正在进行生存分析,我发现在我的数据中,停止时间是相同的,所以我需要通过添加1来使其唯一(停止时间以秒为单位)。
答案 0 :(得分:6)
这是一次尝试。您实际上是按id
和value
进行分组并添加0:(length(value)-1)
。所以:
data[, onemore := value + (0:(.N-1)), by=.(id, value)]
# id value new_value desired_value onemore
#1: 1 95 96 95 95
#2: 1 100 101 100 100
#3: 1 101 102 101 101
#4: 1 101 102 102 102
#5: 1 101 102 103 103
#6: 2 20 21 20 20
#7: 2 35 36 35 35
#8: 2 38 39 38 38
答案 1 :(得分:5)
使用基数R,我们可以使用ave
,其中我们获取每个组的第一个值,并基本上在该组中添加该行的行号。
data$value1 <- ave(data$value, data$id, data$value, FUN = function(x)
x[1] + seq_along(x) - 1)
# id value new_value desired_value value1
#1: 1 95 96 95 95
#2: 1 100 101 100 100
#3: 1 101 102 101 101
#4: 1 101 102 102 102
#5: 1 101 102 103 103
#6: 2 20 21 20 20
#7: 2 35 36 35 35
#8: 2 38 39 38 38
答案 2 :(得分:1)
以下是tidyverse
library(dplyr)
data %>%
group_by(id, value) %>%
mutate(onemore = value + row_number()-1)
# id value onemore
# <chr> <dbl> <dbl>
#1 1 95 95
#2 1 100 100
#3 1 101 101
#4 1 101 102
#5 1 101 103
#6 2 20 20
#7 2 35 35
#8 2 38 38
或者我们可以在没有匿名函数调用的情况下使用base R
data$onemore <- with(data, value + ave(value, id, value, FUN =seq_along)-1)
data$onemore
#[1] 95 100 101 102 103 20 35 38
答案 3 :(得分:1)
为了避免(潜在的代价高昂的)by
,您可以使用 rowid
:
data[, res := value + rowid(id, value) - 1]
# data
# id value new_value desired_value res
# 1: 1 95 96 95 95
# 2: 1 100 101 100 100
# 3: 1 101 102 101 101
# 4: 1 101 102 102 102
# 5: 1 101 102 103 103
# 6: 2 20 21 20 20
# 7: 2 35 36 35 35
# 8: 2 38 39 38 38