Для цикла, чтобы условно перевернуть знак значений во фрейме данных - PullRequest
5 голосов
/ 11 марта 2019

Я пытаюсь создать цикл for в R, который будет 1) идентифицировать отрицательное число как столбец, 2) перевернуть знак в положительный, 3) затем перевернуть знак (в любом направлении) выбранных столбцов для того же строка, а затем создать фактор, определяющий, были ли знаки перевернуты для нет.

Ниже приведен пример. Я хочу, чтобы все отрицательные значения в столбце "z" стали положительными, а затем для любой строки, где это произошло (строки 4-8), я хочу, чтобы знак значений в столбце "y" был перевернут.

Example <- data.frame(x = 4:-3, y = -4:3, z = 2:-5)

   x  y  z
1  4 -4  2
2  3 -3  1
3  2 -2  0
4  1 -1 -1
5  0  0 -2
6 -1  1 -3
7 -2  2 -4
8 -3  3 -5

for (i in Example$z){
 if(sign(i) == -1){
 Example$z[i] <- (Example$z[i]*-1)
 Example$y[i] <- (Example$y[i]*-1)
 Example$Flip[i] <- "True"
 }
 else{
  Example$Flip[i] <- "False"
   }
 }

Однако этот цикл for дает мне следующее:

   x  y  z Flip
1  4 -4  2 True
2  3 -3  1 True
3  2 -2  0 True
4  1 -1 -1 True
5  0  0 -2 True
6 -1 -1  3 True
7 -2 -2  4 True
8 -3 -3  5 True

То, что я хотел создать, это:

   x  y  z Flip
1  4 -4  2 False
2  3 -3  1 False
3  2 -2  0 False
4  1  1  1 True
5  0  0  2 True
6 -1 -1  3 True
7 -2 -2  4 True
8 -3 -3  5 True

Что я делаю не так при построении этого цикла? Любая помощь с благодарностью!

Ответы [ 2 ]

3 голосов
/ 11 марта 2019

В R, в большинстве случаев вы можете уйти без использования for loop

Example$Flip <- Example$z < 0 
Example$z[Example$Flip] <- -Example$z[Example$Flip]
Example$y[Example$Flip] <- -Example$y[Example$Flip]


Example
#   x  y z  Flip
#1  4 -4 2 FALSE
#2  3 -3 1 FALSE
#3  2 -2 0 FALSE
#4  1  1 1  TRUE
#5  0  0 2  TRUE
#6 -1 -1 3  TRUE
#7 -2 -2 4  TRUE
#8 -3 -3 5  TRUE

Используя dplyr, мы могли бы сделать это за одну цепную операцию

library(dplyr)

Example %>%
  mutate(Flip = z < 0, 
         z = ifelse(Flip, -z, z), 
         y = ifelse(Flip, -y, y))

Что касается вашего цикла for, вы циклически изменяете значения z, вместо этого цикл должен иметь индекс z или строки данных (1:nrow(Example)).Я сделал два изменения в вашем коде, и ниже должно работать.

Example$Flip = NA

for (i in seq_along(Example$z)){ #Change1
   if(sign(Example$z[i]) == -1){ #Change2
     Example$z[i] <- (Example$z[i]*-1)
     Example$y[i] <- (Example$y[i]*-1)
     Example$Flip[i] <- "True"
    }
   else{
     Example$Flip[i] <- "False"
   }
 }

Example
#   x  y z  Flip
#1  4 -4 2 False
#2  3 -3 1 False
#3  2 -2 0 False
#4  1  1 1  True
#5  0  0 2  True
#6 -1 -1 3  True
#7 -2 -2 4  True
#8 -3 -3 5  True
0 голосов
/ 11 марта 2019

Ронак абсолютно прав, что в R часто мы можем делать что-то, не используя цикл for. Однако, для вашего собственного назидания, вот ваш цикл for, отрегулированный для получения того, что вы хотите (см. Пояснение ниже).

Обратите внимание, что изначально цикл for использовал фактический элемент (значение z) в качестве i, но вы действительно хотели, чтобы был index (т.е. номер строки) элемент. Таким образом, вы можете изменить что-либо в данном ряду. Мы можем легко сделать это, используя длину (то есть высоту столбцов), а затем итерируя их. В цикле for вы использовали i в качестве индекса. Итак, я оставил все то же самое. Кроме того, отрицательное число учитывается путем проверки, находится ли оно ниже нуля - быстрое исправление.

Приветствия,

Example <- data.frame(x = 4:-3, y = -4:3, z = 2:-5)


for (i in 1:length(Example$z)){
  if(Example$z[i] < 0){
    Example$z[i] <- (Example$z[i]*-1)
    Example$y[i] <- (Example$y[i]*-1)
    Example$Flip[i] <- "True"
  }
  else{
    Example$Flip[i] <- "False"
  }
}

# Example
# x  y z  Flip
# 1  4 -4 2 False
# 2  3 -3 1 False
# 3  2 -2 0 False
# 4  1  1 1  True
# 5  0  0 2  True
# 6 -1 -1 3  True
# 7 -2 -2 4  True
# 8 -3 -3 5  True  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...