Мутировать значения, основанные на относительной позиции строки

Я очищаю некоторые данные, импортированные из Excel. Я пытаюсь создать столбец значений, основанный на положении строки в кадре данных. В частности, я пытаюсь назначить значение для строк между двумя строками с конкретными значениями символов, используя mutate() а также ifelse(), Вот очень упрощенный пример данных, с которыми я работаю:

     a        b    
[1,] "5"      "yes"
[2,] "6"      "no" 
[3,] "7"      "no" 
[4,] "2"      "yes"
[5,] "apple"  NA   
[6,] "4"      "yes"
[7,] "1"      "no" 
[8,] "banana" NA   
[9,] "6"      "yes"
[10,] "3"      "yes"

Я хочу создать c столбец, который возвращает символьное значение цвета, где строки между "apple" а также "banana" (номера строк [6] и [7]) присваиваются c значение столбца "red"и всем другим строкам присваивается значение "blue", Есть ли способ сделать это? Пожалуйста, дайте мне знать, если я смогу объяснить мою проблему более четко!

5 ответов

Решение

Во-первых, ваши данные выглядят как матрица, а не data.frame, которую вы должны исправить, если планируете использовать dplyr. После того, как вы это отсортировали, вы можете использовать cumsum на каждом семестре (отстает, если не хочешь считать apple строки), вычтите, а затем используйте ifelse преобразовать 0 а также 1 в blue а также red:

library(dplyr)

df <- read.table(text = '  a        b    
[1,] "5"      "yes"
[2,] "6"      "no" 
[3,] "7"      "no" 
[4,] "2"      "yes"
[5,] "apple"  NA   
[6,] "4"      "yes"
[7,] "1"      "no" 
[8,] "banana" NA   
[9,] "6"      "yes"
[10,] "3"      "yes"', header = TRUE, stringsAsFactors = FALSE)

rownames(df) <- NULL

df %>% 
    mutate(c = cumsum(lag(a, default = '') == 'apple') - cumsum(a == 'banana'),
           c = ifelse(as.logical(c), 'red', 'blue'))
#>         a    b    c
#> 1       5  yes blue
#> 2       6   no blue
#> 3       7   no blue
#> 4       2  yes blue
#> 5   apple <NA> blue
#> 6       4  yes  red
#> 7       1   no  red
#> 8  banana <NA> blue
#> 9       6  yes blue
#> 10      3  yes blue

С помощью row_number функция от dplyr пакет

#reproducing example
df <- data.frame(a = c("5","6","7","2","apple","4","1","banana","6","3"), b = c("yes","no","no","yes","NA","yes","no","NA","yes","yes"), stringsAsFactors = FALSE)

df$c <- "blue"
lim1 <- which(df$a == "apple")
lim2 <- which(df$a == "banana")

Способ 1:

df$c[lim1:lim2] <- "red"

Способ 2:

library(dplyr)
df <- df %>%
    mutate(c = ifelse(row_number(a) %in% lim1:lim2, "blue", "red"))

Мы можем получить позиции программно, а затем сделать назначение

i1 <- Reduce(`:`, which(is.na(df1$b))+ c(1, -1))
df1$c <- 'blue'
df1$c[i1] <- 'red'

данные

df1 <- structure(list(a = c("5", "6", "7", "2", "apple", "4", "1", "banana", 
"6", "3"), b = c("yes", "no", "no", "yes", NA, "yes", "no", NA, 
"yes", "yes")), .Names = c("a", "b"), class = "data.frame", row.names = c(NA, 
-10L))

Пакет dplyr предлагает row_number() функция, которая может быть использована в сочетании с mutate а также ifelse чтобы назначить значения определенным позициям строки:

library(dplyr)
df = df %>% mutate(c=ifelse(row_number(a) %in% c(6,7),"red","blue"))

С мутациями и dplyr:

df %>% mutate(c = ifelse(row_number() %>% between(match("apple",a)+0.1,match("banana",a)-0.1),"red","blue"))

с базой:

df <- transform(df,c = ifelse(1:nrow(df) > match("apple",a) & (1:nrow(df) < match("banana",a) ),"red","blue"))
Другие вопросы по тегам