R创建一个新列,标识行是否为

时间:2017-06-23 17:08:10

标签: r dataframe duplicates dplyr mutate

我正在尝试创建一个新列,可能是使用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

3 个答案:

答案 0 :(得分:3)

这需要使用 mergedplyr

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中,我们可以使用aveduplicated及其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),]