首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于R中现有标签创建行标签

基于R中现有标签创建行标签
EN

Stack Overflow用户
提问于 2018-03-21 09:06:57
回答 3查看 134关注 0票数 1

我有一个df,它的标签是"S“,我的数字列是<35。我想使用每个S位置,并将前面的3行标记为" S -1“、"S-2”、"S-3“,然后对后面的2行使用"S+1”、"S+2“。

像这样..。

代码语言:javascript
复制
N    S
45   
56   
67   S-3
47   S-2
52   S-1
28   S
89   S+1
66   S+2
55 
76

我用这个来启动我,举个例子。

代码语言:javascript
复制
n <- sample(50:100, 10, replace=T)

data <- data.frame(N=n)
data <- rbind(data, 30)
data <- rbind(data,data,data,data,data,data)
data$S <- ifelse(data$N<35, "S", "")

有什么想法吗..?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-03-21 09:25:14

下面是一个使用base R的选项,其中我们获得'N‘小于35 ('i1')的行索引,创建带有空白("")元素的'S’列,循环遍历'i1',得到3个元素之前的序列,2个元素之后的序列,'S‘的paste,得到带有索引('ind')的序列intersect,并将字符串('val')赋值给'S’列。

代码语言:javascript
复制
i1 <- which(data$N < 35)
data$S <- ""
out <-  do.call(rbind, lapply(i1, function(i) data.frame(ind =(i-3): (i+2), 
   val = c(paste0("S-", 3:1), "S", paste0("S+", 1:2)), stringsAsFactors = FALSE)))
i2 <- out$ind %in% seq_len(nrow(data))

data$S[out$ind[i2]] <- out$val[i2]

数据

代码语言:javascript
复制
set.seed(24)
n <- sample(50:100, 10, replace=T)

data <- data.frame(N=n)
data <- rbind(data, 30)
data <- rbind(data,data,data,data,data,data)
票数 0
EN

Stack Overflow用户

发布于 2018-03-21 09:20:42

在不处理可能的重叠的情况下,这里有一组ifelse()语句来完成工作。也许你可以想出一种更合适的方法来概括它。

您可以将lag()lead()dplyr包一起使用。

代码语言:javascript
复制
data %>% mutate(S = ifelse(S == "S", S,
                           ifelse(lag(S == "S"), "S+1",
                                  ifelse(lag(S == "S", 2), "S+2",
                                         ifelse(lead(S == "S"), "S-1",
                                                ifelse(lead(S == "S", 2), "S-2", ""))))),
                S = ifelse(is.na(S), "", S))

(如果第一个值不小于35,您将在前两行中获得NA值,因此将这些值替换为“”。)

代码语言:javascript
复制
     N   S
1   52    
2   86    
3   86    
4   57    
5   54    
6   57    
7   51    
8   98    
9  100 S-2
10  73 S-1
11  30   S
12  52 S+1
13  86 S+2
14  86   
票数 0
EN

Stack Overflow用户

发布于 2018-03-21 09:51:55

这是一个很长的答案,因为我把它分解成了一些片段,我通常会使用管道和lambda表达式来实现它,但是它应该很容易遵循。

我将处理行索引,并计算两个向量,一个向量包含左边最接近i的具有标签"S"的索引,另一个包含右边最接近i的索引。

代码语言:javascript
复制
indices <- 1:length(data$S)
closest_left  <- rep(NA, length = length(indices))
closest_right <- rep(NA, length = length(indices))

我使用purrr的精简函数来计算这些函数,但是您也可以很容易地在一个循环中这样做。

代码语言:javascript
复制
this_or_left <- function(left_val, i) { 
    res <- if (data$S[[i]] == "S") i else left_val
    closest_left[[i]] <<- if (data$S[[i]] == "S") i else left_val
}
this_or_right <- function(right_val, i) { 
    res <- if (data$S[[i]] == "S") i else right_val
    closest_right[[i]] <<- if (data$S[[i]] == "S") i else right_val
}

purrr::reduce(indices, this_or_left, .init = this_or_left(NA, 1))
purrr::reduce_right(indices, this_or_right, .init = this_or_right(NA, length(indices)))

我不知道你能不能用矢量表达。有可能。我没试过。

现在,我只需计算到最近的S的距离,然后根据它制作标签,如果距离大于3,使用空标签,如果距离为零,则使用标签"S"

代码语言:javascript
复制
get_dist <- Vectorize(function(i) {
    down <- i - closest_left[i] 
    up <- closest_right[i] - i
    if (is.na(down) || down > up) up
    else if (is.na(up) || down <= up) -down
    else NA
})
make_label <- Vectorize(function(dist) {
    if (abs(dist) > 3) ""
    else if (dist == 0) "S"
    else if (dist < 0) paste0("S", dist)
    else if (dist > 0) paste0("S+", dist)
})

make_label(get_dist(indices))

在这里,我使用了Vectorized表达式来稍微修改它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49402073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档