Условная замена значений в данных.рамка
я пытаюсь понять, как условно заменить значения в фрейме данных без использования цикла. Мой фрейм данных структурирован следующим образом:
> df
a b est
1 11.77000 2 0
2 10.90000 3 0
3 10.32000 2 0
4 10.96000 0 0
5 9.90600 0 0
6 10.70000 0 0
7 11.43000 1 0
8 11.41000 2 0
9 10.48512 4 0
10 11.19000 0 0
и dput
выход такой:
structure(list(a = c(11.77, 10.9, 10.32, 10.96, 9.906, 10.7,
11.43, 11.41, 10.48512, 11.19), b = c(2, 3, 2, 0, 0, 0, 1, 2,
4, 0), est = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), .Names = c("a",
"b", "est"), row.names = c(NA, -10L), class = "data.frame")
что я хочу сделать, это проверить значение b
. Если b
равно 0, я хочу установить est
значением a
. Я понимаю, что df$est[df$b == 0] <- 23
установит все значения est
в 23, когда b==0
. То, что я не понимаю, как установить est
в значение a
когда это условие истинно. Например:
df$est[df$b == 0] <- (df$a - 5)/2.533
дает следующее предупреждение:
Warning message:
In df$est[df$b == 0] <- (df$a - 5)/2.533 :
number of items to replace is not a multiple of replacement length
есть ли способ, которым я могу передать соответствующую ячейку, а не вектор?
6 ответов:
так как вы условно индексируете
df$est
, вам также нужно условно индексировать вектор заменыdf$a
:index <- df$b == 0 df$est[index] <- (df$a[index] - 5)/2.533
конечно, переменная
index
это временно, и я использую его, чтобы сделать код немного более readible. Вы можете написать его в один шаг:df$est[df$b == 0] <- (df$a[df$b == 0] - 5)/2.533
для еще лучшей читаемости, вы можете использовать
within
:df <- within(df, est[b==0] <- (a[b==0]-5)/2.533)
результаты, независимо от того, какой способ вы выберете:
df a b est 1 11.77000 2 0.000000 2 10.90000 3 0.000000 3 10.32000 2 0.000000 4 10.96000 0 2.352941 5 9.90600 0 1.936834 6 10.70000 0 2.250296 7 11.43000 1 0.000000 8 11.41000 2 0.000000 9 10.48512 4 0.000000 10 11.19000 0 2.443743
как и другие указали, альтернативным решением в вашем примере является использование
ifelse
.
попробовать данные.таблица ' s
:=
оператор :DT = as.data.table(df) DT[b==0, est := (a-5)/2.533]
это быстро и коротко. Увидеть эти вопросы, для получения дополнительной информации о
:=
:почему данные.таблица определена
:=
когда я должен использовать
:=
операторdata.table
вот один подход.
ifelse
векторизуется и проверяет все строки на нулевые значенияb
и заменяетest
С(a - 5)/2.53
если это так.df <- transform(df, est = ifelse(b == 0, (a - 5)/2.53, est))
The Р-Инферно, или основная R-документация объяснит, почему использование df$* не является лучшим подходом здесь. На странице справки для " [":
"индексирование по [ похоже на атомарные векторы и выбирает список указанных элементов. Оба [[ и $ выберите один элемент списка. Основное различие заключается в том, что $ не позволяет вычислять индексы, тогда как [[ делает. х$название эквивалентно X[["имя", точно = ложь]]. Кроме того, частичное совпадение поведения [[can управляется с помощью точного аргумента. "
Я рекомендую использовать Примечание. Пример:
Rgames: foo x y z [1,] 1e+00 1 0 [2,] 2e+00 2 0 [3,] 3e+00 1 0 [4,] 4e+00 2 0 [5,] 5e+00 1 0 [6,] 6e+00 2 0 [7,] 7e+00 1 0 [8,] 8e+00 2 0 [9,] 9e+00 1 0 [10,] 1e+01 2 0 Rgames: foo<-as.data.frame(foo) Rgames: foo[foo$y==2,3]<-foo[foo$y==2,1] Rgames: foo x y z 1 1e+00 1 0e+00 2 2e+00 2 2e+00 3 3e+00 1 0e+00 4 4e+00 2 4e+00 5 5e+00 1 0e+00 6 6e+00 2 6e+00 7 7e+00 1 0e+00 8 8e+00 2 8e+00 9 9e+00 1 0e+00 10 1e+01 2 1e+01
другой вариант-использовать case_when
require(dplyr) transform(df, est = case_when( b == 0 ~ (a - 5)/2.53, TRUE ~ est ))
это решение становится еще более удобным, если необходимо выделить более 2 случаев, так как это позволяет избежать вложенных
if_else
конструктов.
вот мое решение с другой версией, чтобы решить мою проблему с if и max в строке .
my.assign <- function(col1, col2, col3){ if(col2==0) {col3 <- col1} else { col3 <- 0 } } my.max <- function(col1, col2, col3){ if(col1 >= 10 ) {max_r <- max(col2, col3, na.rm=TRUE)} else { max_r <- col2 } } df$est <- with(df,mapply(my.assign,col1=a, col2=b, col3=est)) df$max_row <- with(df,mapply(my.max,col1=a, col2=b, col3=est)) > df a b est max_row 1 11.77000 2 0.000 2.00 2 10.90000 3 0.000 3.00 3 10.32000 2 0.000 2.00 4 10.96000 0 10.960 10.96 5 9.90600 0 9.906 0.00 6 10.70000 0 10.700 10.70 7 11.43000 1 0.000 1.00 8 11.41000 2 0.000 2.00 9 10.48512 4 0.000 4.00 10 11.19000 0 11.190 11.19