Использование оператора if в apply в R для каждого значения во фрейме данных - PullRequest
2 голосов
/ 21 января 2020

У меня есть фрейм данных, который я создал с помощью функции read_excel, а затем продублировал его. Я собираюсь объяснить это, как если бы я использовал Excel, потому что это так легко сделать в Excel. Я хочу проверить, есть ли в каждой ячейке каждой строки в столбцах с 3 по 11 ноль, и если да, то поставить ноль в столбцах с 12 по 20. Если нет, сохранить исходное значение.

Data2 <- Data1

Data2[,12:20] <- apply(Data1[,3:11],1:2,function(x) {if(x==0) {0})

Это это сообщение об ошибке, которое я получаю:

Предупреждение: In [<-.data.frame (*tmp*,, 12:20, значение = список (0, 0, 0, 0, 0,: при условии 450) переменные для замены 9 переменных

Пример:

Data1 <- matrix(data=c(0,1,1,0,3,4,5,6,2,3,0,5,6,5,6,2,6,2,3,4,5,6,5,6),nrow=6,ncol=4)
Data2 <- Data1
Data2[,3:4] <- apply(Data1[,1:2],1:2,function(x) if(x==0) {0})
Data2 <- matrix(Data2,nrow=6,ncol=4)

Результат должен выглядеть следующим образом:

     [,1] [,2] [,3] [,4]
[1,]    0    5    0    3
[2,]    1    6    5    4
[3,]    1    2    6    5
[4,]    0    3    0    6
[5,]    3    0    6    0
[6,]    4    5    2    6

, где любой ноль в столбцах 1 и 2 становится нули в соответствующем месте в столбцах 3 и 4.

Вместо этого я получаю это:

     [,1] [,2] [,3] [,4]
[1,] 0    5    0    NULL
[2,] 1    6    NULL NULL
[3,] 1    2    NULL NULL
[4,] 0    3    0    NULL
[5,] 3    0    NULL 0   
[6,] 4    5    NULL NULL

Кроме того, я все еще получаю то же сообщение об ошибке из исходных данных, которые имели 50 + строка и 20 столбцов показаны в начале.

Ответы [ 3 ]

1 голос
/ 22 января 2020

Вот альтернативное решение:

Сначала создайте логическую матрицу, представляющую, какие элементы равны 0 в интересующих столбцах.

mat <- Data1[,1:2] == 0
mat

      [,1]  [,2]
[1,]  TRUE FALSE
[2,] FALSE FALSE
[3,] FALSE FALSE
[4,]  TRUE FALSE
[5,] FALSE  TRUE
[6,] FALSE FALSE

Затем выберите элементы для целевых столбцов где логическая матрица имеет значение TRUE и задает для них значение 0:

Data2[,3:4][mat==TRUE] <- 0
Data2

     [,1] [,2] [,3] [,4]
[1,]    0    5    0    3
[2,]    1    6    5    4
[3,]    1    2    6    5
[4,]    0    3    0    6
[5,]    3    0    6    0
[6,]    4    5    2    6
1 голос
/ 21 января 2020

Возможно, есть более элегантное решение, но оно работает:

for (j in seq(nrow(Data1))) {

  for (i in seq(2)) {

    if (Data1[j,i] == 0) {

      Data1[j,i + 2] <- 0

    }
  }
}

Результат:

> Data1
     [,1] [,2] [,3] [,4]
[1,]    0    5    0    3
[2,]    1    6    5    4
[3,]    1    2    6    5
[4,]    0    3    0    6
[5,]    3    0    6    0
[6,]    4    5    2    6

Очевидно, вы захотите настроить 2 в i in seq(2) и Data[j,i + 2] <- 0, чтобы соответствовать правильному количеству столбцов, по которым вы итерируете это.

0 голосов
/ 21 января 2020

С R вы всегда хотите работать с векторами, ifelse - отличный способ сделать оператор if для вектора. Обычно это медленно для циклов в R и применения функции к каждому элементу в матрице. Я считаю, что это зарезервировано для другой функции применения, но я не знаю, какая именно. Прикладные программы также чувствительны к типам возвращаемых данных. Таким образом, вы пытаетесь добавить фрейм данных, используя стандартное применение и работая со столбцами (так как ожидается, что большинство фреймов данных в R будут обрабатываться), что позволяет легко добавлять дополнительные столбцы.

Data2[,12:20] <- apply(Data1[,3:11], 2, function(x){ifelse(x==0,0,x)})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...