从现有data.frame中的两个条件创建新的字符串变量

时间:2014-04-03 17:04:39

标签: r dataframe vectorization subset

我有一个data.frame,我想根据两个条件创建一个新变量。 (1)新变量是一个预定义的字符串,对应于data.frame中变量MONTH的现有值范围,(2)这些字符串取决于变量{{的正或负状态。 1)}在data.frame中。

现在,我为正面和负面X值创建子集,然后执行以下操作:

X

我正在考虑做month.neg <- subset(month,X < 0) month.pos <- subset(month,X > 0) month.pos$SEA[month.pos$MONTH == 12 | month.pos$MONTH == 1 | month.pos$MONTH == 2] <- "Winter" month.pos$SEA[month.pos$MONTH == 3 | month.pos$MONTH == 4 | month.pos$MONTH == 5] <- "Spring" month.pos$SEA[month.pos$MONTH == 6 | month.pos$MONTH == 7 | month.pos$MONTH == 8] <- "Summer" month.pos$SEA[month.pos$MONTH == 9 | month.pos$MONTH == 10 | month.pos$MONTH == 11] <- "Fall" month.neg$SEA[month.neg$MONTH == 12 | month.neg$MONTH == 1 | month.neg$MONTH == 2] <- "Summer" month.neg$SEA[month.neg$MONTH == 3 | month.neg$MONTH == 4 | month.neg$MONTH == 5] <- "Fall" month.neg$SEA[month.neg$MONTH == 6 | month.neg$MONTH == 7 | month.neg$MONTH == 8] <- "Winter" month.neg$SEA[month.neg$MONTH == 9 | month.neg$MONTH == 10 | month.neg$MONTH == 11] <- "Spring" month.new <- rbind(month.neg, month.pos) 这样的事情,但这并不适用于data.frame(即if(month$X > 0))。

虽然上述方法有效,但似乎很冗长。对这个问题有一个不那么冗长的方法吗?我应该考虑哪些包装或程序?

error: the condition has length > 1 and only the first element will be used

1 个答案:

答案 0 :(得分:1)

那是因为ifelse是矢量化而if不是。你想要这样的东西:

month_map <- rep(c("Winter", "Spring", "Summer", "Fall"), each = 3)
month_map <- c(month_map[-1], month_map[1]) # tag December to be Winter

month.pos$SEA <- month_map[1 + (month.pos$MONTH - 1 + ifelse(month$X < 0, 6, 0)) %% 12]

如果ifelse(month$X < 0, 6, 0)为负(即您位于南半球),则X语句将增加6个月,这与您上面的分类相对应。由于添加了%% 12ifelse技巧会将13和14之类的内容回滚到1和2。

实施例

month.pos <- data.frame(MONTH = round(runif(100, 1, 12)))
month <- data.frame(X = runif(100, -1, 1))
head(cbind(month.pos, month), 10)
 #    MONTH           X
 # 1      8 -0.55105406
 # 2      3  0.97186211
 # 3      9 -0.99687710
 # 4      6 -0.92899175
 # 5      7 -0.61108006
 # 6     10  0.66565870
 # 7      4  0.77975565
 # 8     10 -0.54498417
 # 9      7 -0.04759831
 # 10    10 -0.26378151

 month.pos$SEA <- month_map[1 + (month.pos$MONTH - 1 + ifelse(month$X < 0, 6, 0)) %% 12]
 head(month.pos, 10)
 #    MONTH    SEA
 # 1      8 Winter
 # 2      3 Spring
 # 3      9 Spring
 # 4      6 Winter
 # 5      7 Winter
 # 6     10   Fall
 # 7      4 Spring
 # 8     10 Spring
 # 9      7 Winter
 # 10    10 Spring