R:基于众多截止条件创建新虚拟变量的最佳方法是什么?

时间:2016-04-20 17:10:28

标签: r

在给定许多条件的情况下,创建虚拟变量的最简单方法是什么。

例如,假设我有以下数据帧(数据):

birth    ID
1958     176
1958     178
1959     300
1959     301
1960     500
1960     600
1961     216
1961     201
1962     100

我想创建一个符合条件的新变量,如果满足以下任一条件,则为1:

出生年份是1958年,身份证号码大于175;出生年份是1959年,ID大于320,出生年份是1960年,ID大于341 ......依此类推。

我知道我可以用许多ifelse命令做到这一点,但我希望有一种更简约的方法来做到这一点。

数据

data <- structure(list(birth = c(1958L, 1958L, 1959L, 1959L, 1960L, 1960L, 1961L, 1961L, 1962L),
                       ID = c(176L, 178L, 300L, 301L, 500L, 600L, 216L, 201L, 100L)),
                  .Names = c("birth", "ID"), class = "data.frame", row.names = c(NA, -9L))

4 个答案:

答案 0 :(得分:6)

又一种方式

data <- structure(list(birth = c(1958L, 1958L, 1959L, 1959L, 1960L, 1960L, 1961L, 1961L, 1962L),
                       ID = c(176L, 178L, 300L, 301L, 500L, 600L, 216L, 201L, 100L)),
                  .Names = c("birth", "ID"), class = "data.frame", row.names = c(NA, -9L))

假设您有一个年份的向量匹配1-1与ID切割点,例如

year <- data$birth
id <- c(175, 320, 341, seq(360, 1000, length.out = 6))

cbind(year, id)
#      year   id
# [1,] 1958  175
# [2,] 1958  320
# [3,] 1959  341
# [4,] 1959  360
# [5,] 1960  488
# [6,] 1960  616
# [7,] 1961  744
# [8,] 1961  872
# [9,] 1962 1000

使用match

within(data, idx <- +(ID[match(birth, year)] >= id))

#   birth  ID idx
# 1  1958 176   1
# 2  1958 178   0
# 3  1959 300   0
# 4  1959 301   0
# 5  1960 500   1
# 6  1960 600   0
# 7  1961 216   0
# 8  1961 201   0
# 9  1962 100   0

答案 1 :(得分:4)

您可以使用Reduce类型操作。例如

years <- 1958:1960
ids <- c(175, 320, 341)
Reduce(function(a, b) {
    a | (data$birth==b[[1]] & data$ID>b[[2]])
}, Map(list, years, ids), init=F)

在这里,我们使用Map制作年份/ ID对,然后使用Reduce进行迭代。基本上它将所有条件组合在一起。对于匹配的任何行,这将返回TRUE。

答案 2 :(得分:4)

需要改变名称,但这种方法适合加入:

library(data.table)

lookupDF = data.table(birth=c(1958,1959,1960), ID=c(175,320,341))

lookupDF[setDT(data), on='birth'][,ID:=+(ID>=i.ID)]
#   birth ID i.ID
#1:  1958  0  176
#2:  1958  0  178
#3:  1959  1  300
#4:  1959  1  301
#5:  1960  0  500
#6:  1960  0  600
#7:  1961 NA  216
#8:  1961 NA  201
#9:  1962 NA  100

答案 3 :(得分:2)

您可以使用粘贴来创建具有逻辑条件的字符串。然后需要对该字符串进行评估,以便在ifelse中使用。

cond = paste("(df$birth >", c(1958:1960),"& df$ID >", c(175, 320, 341), ")", collapse=" | ")

ifelse(eval(parse(text=cond)), 1,0)