Мутировать значения, основанные на относительной позиции строки
Я очищаю некоторые данные, импортированные из 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"))