如何在R中创建“max”虚拟变量?

时间:2016-07-15 13:43:49

标签: r dataframe machine-learning data.table

我想创建一个“max”和一个条件虚拟变量。假设我有一个看起来像这样的数据集:

   Subject  Year    X   Ydummy
       A    1990    0   0
       A    1991    1   0
       A    1992    2   0
       A    1993    0   0
       A    1995    1   0
       A    1996    2   0
       A    1997    3   0
       B    1990    0   0
       B    1991    0   0
       B    1992    0   0
       B    1993    1   0
       B    1995    2   0
       B    1996    3   0
       B    1997    3   0
       C    1990    1   0
       C    1991    2   0
       C    1992    3   0
       C    1993    3   0
       C    1995    3   0
       C    1996    3   0
       C    1997    3   0
       C    1998    3   1
       D    1990    0   0
       D    1991    0   0
       D    1992    1   0
       D    1993    2   0
       D    1995    3   0
       D    1996    3   0
       D    1997    4   0

X变量是一个累积变量(测量每个学科年)。

(1)我想创建一组“max”虚拟变量:表示X是否已达到最大值1,2,3的假人,依此类推。 为了简化,假设我在这里有兴趣创建变量“Xmax3”“Xmax3”表示X的最大值是否等于3(对于每个主题年)。如果最大X值为3,则“Xmax3”为1,否则为0。让它变得复杂的是,只有当X第一次变为3时,我才希望它为1。或者第一次达到最大值。请参阅下面的示例。

我尝试使用以下方法创建此变量:

data$Xmax3 <- ave(data$X, data$Subject, FUN = function(x) if (max(x) == 3) 1 else 0) 

但它不能控制0,而且我希望它在X变为3时只能为1。

(2)基于“Xmax3”我想生成一个条件虚拟变量“”Xmax3_noY“。这个变量应该表明是否X达到最大值3后5年后Y为1.如果5年后Y为1,则“”Xmax3_noY“应为0.

因此,如果您查看下面的示例,您会看到C – 1992“Xmax3”为1。但是“”Xmax3_noY“为0,因为C – 1998的Y为1如果1999年的Y为1(6年后),那么”“Xmax3_noY” woudl也是1。

示例(理想结果):

Subject     Year    X   Ydummy  Xmax3   Xmax3_noY
       A    1990    0      0      0        0
       A    1991    1      0      0        0
       A    1992    2      0      0        0
       A    1993    0      0      0        0
       A    1995    1      0      0        0
       A    1996    2      0      0        0
       A    1997    3      0      1        1
       B    1990    0      0      0        0
       B    1991    0      0      0        0
       B    1992    0      0      0        0
       B    1993    1      0      0        0
       B    1995    2      0      0        0
       B    1996    3      0      1        1
       B    1997    3      0      0        0
       C    1990    1      0      0        0
       C    1991    2      0      0        0
       C    1992    3      0      1        0
       C    1993    3      0      0        0
       C    1995    3      0      0        0
       C    1996    3      0      0        0
       C    1997    3      0      0        0
       C    1998    3      1      0        0
       D    1990    0      0      0        0
       D    1991    0      0      0        0
       D    1992    1      0      0        0
       D    1993    2      0      0        0
       D    1995    3      0      0        0
       D    1996    3      0      0        0
       D    1997    4      0      0        0

你会如何创建这两个变量?我非常感谢任何“教学”的建议(如果可能的话),允许我试验这些变量的不同版本。

可重复的样本:

> dput(data)
structure(list(Subject = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 
1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L), .Label = c("A", "B", "C", "D"), class = "factor"), 
    Year = c(1990L, 1991L, 1992L, 1993L, 1995L, 1996L, 1997L, 
    1990L, 1991L, 1992L, 1993L, 1995L, 1996L, 1997L, 1990L, 1991L, 
    1992L, 1993L, 1995L, 1996L, 1997L, 1998L, 1990L, 1991L, 1992L, 
    1993L, 1995L, 1996L, 1997L), X = c(0L, 1L, 2L, 0L, 1L, 2L, 
    3L, 0L, 0L, 0L, 1L, 2L, 3L, 3L, 1L, 2L, 3L, 3L, 3L, 3L, 3L, 
    3L, 0L, 0L, 1L, 2L, 3L, 3L, 4L), Ydummy = c(0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c("Subject", 
"Year", "X", "Ydummy"), class = "data.frame", row.names = c(NA, 
-29L))

编辑(与StevenBeaupré交谈后):

Xmax3 变量应指示何时达到X的第一个最大值,即在这种情况下X达到3的时间。

对于 Xmax3_noY 变量,条件是:如果在X达到最大(和第一)值3之后数据集中的后5年中Y == 1,那么 Xmax3_noY == 0。 换句话说,如果Xmax_noY == 1

中没有Ydummy == 1,则(Year +5)

此外,最好将 Xmax3_noY 变量调整为不仅在5年后的 ,而且之前的。换句话说: Xmax_noY == 1 如果它不是 Ydummy == 1 (Year-5):( Year + 5)

3 个答案:

答案 0 :(得分:2)

library(data.table)
dt = as.data.table(data) # or setDT to convert in place

dt[, Xmax3 := 0][X == 3, Xmax3 := c(1, rep(0, .N-1)), by = Subject][
                       , Xmax3 := if (max(X) > 3) 0, by = Subject]
dt[, Xmax3_noY := 0][X == 3,
                     Xmax3_noY := if(all(Ydummy[Year <= Year[1] + 6] == 0)) Xmax3 else 0,
                     by = Subject]
dt
#    Subject Year X Ydummy Xmax3 Xmax3_noY
# 1:       A 1990 0      0     0         0
# 2:       A 1991 1      0     0         0
# 3:       A 1992 2      0     0         0
# 4:       A 1993 0      0     0         0
# 5:       A 1995 1      0     0         0
# 6:       A 1996 2      0     0         0
# 7:       A 1997 3      0     1         1
# 8:       B 1990 0      0     0         0
# 9:       B 1991 0      0     0         0
#10:       B 1992 0      0     0         0
#11:       B 1993 1      0     0         0
#12:       B 1995 2      0     0         0
#13:       B 1996 3      0     1         1
#14:       B 1997 3      0     0         0
#15:       C 1990 1      0     0         0
#16:       C 1991 2      0     0         0
#17:       C 1992 3      0     1         0
#18:       C 1993 3      0     0         0
#19:       C 1995 3      0     0         0
#20:       C 1996 3      0     0         0
#21:       C 1997 3      0     0         0
#22:       C 1998 3      1     0         0
#23:       D 1990 0      0     0         0
#24:       D 1991 0      0     0         0
#25:       D 1992 1      0     0         0
#26:       D 1993 2      0     0         0
#27:       D 1995 3      0     0         0
#28:       D 1996 3      0     0         0
#29:       D 1997 4      0     0         0
#    Subject Year X Ydummy Xmax3 Xmax3_noY

答案 1 :(得分:1)

这是一个解决方案,可以从1到4(8个新列)生成列Xmax_nXmax_n_noY,并满足以下条件:

  • 1 X列{/ 1}} SubjectXmax_n的{​​{1}}的第一个最大值表示
  • 如果0Xmax_n_noY的{​​{1}}值为Xmax_n,则Ydummy为每个1值显示Subject列的值在Year之前或之后的5年范围内组合,否则为1
library(dplyr)
library(tidyr)

data %>%
  group_by(Subject, X) %>%
  mutate(maxt   = ifelse(X != 0 & row_number(X) == 1, paste0("Xmax", X), NA),
         maxnoy = ifelse(!is.na(maxt), paste0("Xmax", X, "_noY"), NA),
         val    = ifelse(!is.na(maxt), 1, 0)) %>%
  group_by(Subject) %>%
  mutate(Y2  = ifelse(!is.na(maxnoy) & any(Ydummy == 1), Year[Ydummy == 1], NA),
         L   = ifelse(!is.na(maxnoy) & !is.na(Y2), Y2 %in% list((Year-5):(Year+5)), 1)) %>%
  spread(maxnoy, L, fill = 0) %>%
  spread(maxt, val, fill = 0) 

在第一部分中,我们group_by() SubjectX生成三个重要的新列maxtvalmaxnoy < / p>

data %>%
  group_by(Subject, X) %>%
  mutate(maxt   = ifelse(X != 0 & row_number(X) == 1, paste0("Xmax", X), NA),
         maxnoy = ifelse(!is.na(maxt), paste0("Xmax", X, "_noY"), NA),
         val    = ifelse(!is.na(maxt), 1, 0)) %>%

然后我们生成重要性L的第四列,如果0中的Xmax_n值为Ydummy,则1Subject Year {1}} 1之前或之后5年内的{1}}组,否则为 group_by(Subject) %>% mutate(Y2 = ifelse(!is.na(maxnoy) & any(Ydummy == 1), Year[Ydummy == 1], NA), L = ifelse(!is.na(maxnoy) & !is.na(Y2), Y2 %in% list((Year-5):(Year+5)), 1)) %>%

spread()

然后我们maxt成对val&amp; maxnoyL&amp; spread(maxnoy, L, fill = 0) %>% spread(maxt, val, fill = 0) 以获得所需的输出格式。

private static readonly ConcurrentDictionary<string, Lazy<Task>> RefreshTokenTasks = new ConcurrentDictionary<string, Lazy<Task>>();

答案 2 :(得分:-1)

如果您的数据不是很大,您可以使用循环来解决问题。这通常被视为不好,但您可以轻松地将以下循环的命令转换为函数,以便通过apply执行该函数(请参阅。?apply

所以,我们假设data_size是数据的长度,即data_size <- dim(data)[1],那么您可以分两步计算Xmax3列。首先是以下循环:

data$Xmax3 <- 0
for (t in 1:data_size) {
  if (data$X[t] == 3) {
    data$Xmax3[t] <- 1
  }
}

如果您愿意使用dplyr,也可以更优雅地表达:

data <- dplyr::mutate(data,Xmax3 = ifelse ((X == 3), 1 , 0)) 

然后在第二步中我们要消除所有1后面的1.再次,有多种方法可以实现这一点。一种可能性是使用diff(x)函数(请参阅:?diff)。它返回x值之间的差异。例如:diff(c(1,2,5,6,1))将返回'1 3 1 -5'。请注意,返回的向量比提供的向量短一个,因为差异是采用的。接下来的部分有点笨拙,因为Xmax3_diff我们需要将Xmax3行的第一个值连接起来并删除0以下的所有值:

Xmax3_diff <- diff(data$Xmax3)
data$Xmax3 <- pmax( c(data$Xmax3[1],Xmax3_diff) , 0)

完成此操作后,可以使用循环再次获取列Xmax3_noY。这次我们关心数据的最后一行 - 条目!

buffer <- 5 # 5 because we want to check 5 years a head of the current time step
data$Xmax3_noY <- 0
for (t in 1:(data_size-buffer)) {
  # check if the the next 5 years of the Ydummy column are all 0
  test_for_followup_years <- any(data$Ydummy[t:(t+buffer)] == 0) 
  # If hte conditions we want are met, then set max3_noY to 1
  if ( (data$Xmax3[t] == 1) & test_for_followup_years ) {
    data$Xmax3_noY[t] <- 1
  }
}