我正在尝试创建一个新列,可能是使用mutate,它将确定该行是否符合一些条件。基本上,对于每个用户,我想确定某个DataCode的最后一行(按时间)。只有一些数据代码适用(下例中为1000和2000),其他数据代码应返回NA(此处为3000)。我一直试图在脑海中解决这个问题,而我所能想到的只是一个包含许多If语句的长变异项。有更优雅的方式吗?
下面的IsFinal列显示了产品的含义。
User Time DataCode Data IsFinal
101 10 1000 50 0
101 20 2000 300 1
101 30 3000 150 NA
101 40 1000 250 1
101 50 3000 300 NA
102 10 2000 50 0
102 20 1000 150 0
102 30 1000 150 0
102 40 2000 350 1
102 50 3000 150 NA
102 60 1000 50 1
答案 0 :(得分:3)
这需要使用 merge
和dplyr
包 :
library(dplyr)
new.tab <- query.tab %>%
group_by(User, DataCode) %>%
arrange(Time) %>%
filter(DataCode != 3000) %>%
mutate(IsFinal = ifelse(row_number()==n(),1,0))
fin.tab <- merge(new.tab, query.tab, all.x = FALSE, all.y = TRUE)
如果您想在dplyr
中执行 所有内容,那么这就是您的答案:
fin.tab <-
query.tab %>%
group_by(User, DataCode) %>%
arrange(User,Time) %>%
mutate(IsFinal = ifelse(DataCode == 3000 , NA,
ifelse(row_number()==n(),1,0)))
这两个解决方案都将提供:
> fin.tab
# User Time DataCode Data IsFinal
# 1 101 10 1000 50 0
# 2 101 20 2000 300 1
# 3 101 30 3000 150 NA
# 4 101 40 1000 250 1
# 5 101 50 3000 300 NA
# 6 102 10 2000 50 0
# 7 102 20 1000 150 0
# 8 102 30 1000 150 0
# 9 102 40 2000 350 1
# 10 102 50 3000 150 NA
# 11 102 60 1000 50 1
<强> 数据:的强>
query.tab <- structure(list(User = c(101L, 101L, 101L, 101L, 101L, 102L, 102L,
102L, 102L, 102L, 102L), Time = c(10L, 20L, 30L, 40L, 50L, 10L,
20L, 30L, 40L, 50L, 60L), DataCode = c(1000L, 2000L, 3000L, 1000L,
3000L, 2000L, 1000L, 1000L, 2000L, 3000L, 1000L), Data = c(50L,
300L, 150L, 250L, 300L, 50L, 150L, 150L, 350L, 150L, 50L)), .Names = c("User",
"Time", "DataCode", "Data"), row.names = c(NA, -11L), class = "data.frame")
注意: 读取修改历史记录。它可以为您提供一些如何处理类似问题的见解。
答案 1 :(得分:2)
您是否可以制作一系列经批准的代码?这会使if
语句更加简单。
# Can you obtain list of viable codes?
codes <- c("2000", "1000")
# Can you put them in order?
goodcodes <- codes[order(codes)]
# last item in ordered goodcodes should be the end code
endcode <- goodcodes[length(goodcodes)]
testcodes <- c("0500", "1000", "2000", "3000")
n <- length(testcodes)
IsFinal <- rep(0, n)
for (i in 1:n) {
if (testcodes[i] %in% goodcodes) {
if (testcodes[i] == endcode) (IsFinal[i] = 1)
} else (IsFinal[i] = NA)
}
> IsFinal
[1] NA 0 1 NA
>
答案 2 :(得分:2)
在基数R中,我们可以使用ave
和duplicated
及其fromLast
参数来获取二进制值。然后用NA替换所需的值。使用@ masoud的答案中的数据。
# get binary values for final DataCode by user
query.tab$IsFinal <- with(query.tab,
ave(DataCode, User, FUN=function(x) !duplicated(x, fromLast=TRUE)))
# Fill in NA values
is.na(query.tab$IsFinal) <- query.tab$DataCode %in% c(3000)
返回
query.tab
User Time DataCode Data IsFinal
1 101 10 1000 50 0
2 101 20 2000 300 1
3 101 30 3000 150 NA
4 101 40 1000 250 1
5 101 50 3000 300 NA
6 102 10 2000 50 0
7 102 20 1000 150 0
8 102 30 1000 150 0
9 102 40 2000 350 1
10 102 50 3000 150 NA
11 102 60 1000 50 1
请注意,这假定数据按用户时间排序。这可以通过在使用上述代码之前调用order
来实现。
query.tab <- query.tab[order(query.tab$User, query.tab$Time),]