Условия и вычитание из матрицы в R - PullRequest
0 голосов
/ 09 ноября 2018

Я смотрел на R, создавая вектор из условной операции над матрицей , и использование аналогичного решения не дает того, что я хочу (и я не уверен, почему).

Моя цель - оценить df со следующим условием: if df > 2, df -2, else 0

Взять df:

a <- seq(1,5)
b <- seq(0,4)
df <- cbind(a,b) %>% as.data.frame()

df это просто:

a b
1 0
2 1
3 2
4 3
5 4

df_final должно выглядеть следующим образом после подходящей функции:

a b
0 0
0 0
1 0
2 1
3 2

Я применил следующую функцию к результату, и я не уверен, почему она не работает (приветствуется дальнейшее объяснение решения)

apply(df,2,function(df){
     ifelse(any(df>2),df-2,0)
 })

Выходит следующее:

 a  b 
-1 -2

Спасибо, ТАКОЕ сообщество!

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Создайте набор данных 'out', вычитая 2, а затем замените значения, основанные на логическом условии, на 0

out <- df - 2
out[out < 0] <- 0

или за один шаг

(df-2) * ((df - 2) > 0)
0 голосов
/ 09 ноября 2018

Давайте исправим вашу функцию и поймем, почему она не работает:

apply(df,  # apply to df
       2,  # to each *column* of df 
       function(df){  # this function. Call the function argument (each column) df 
                      #  (confusing because this is the same name as the data frame...)
         ifelse(  # Looking at each column...
              any(df > 2),  # if there are any values > 2
              df - 2,       # then df - 2
              0             # otherwise 0
          )
 })

any() возвращает одно значение. ifelse() возвращает что-то такое же, что и у теста, поэтому, сделав ваш тест any(df > 2) (одно значение), ifelse() также вернет одно значение.

Давайте исправим это, (а) изменив функцию на имя, отличное от входного (для удобства чтения) и (б) избавившись от any:

apply(df,  # apply to df
       2,  # to each *column* of df 
       function(x){   # this function. Call the function argument (each column) x
         ifelse(  # Looking at each column...
              x > 2,  # when x is > 2
              df - 2, # make it x - 2
              0       # otherwise 0
          )
 })

apply предназначен для работы с матрицами. Когда вы даете ему фрейм данных, первым делом он конвертирует его в матрицу. Если вы хотите, чтобы результат был фреймом данных, вам необходимо преобразовать его обратно во фрейм данных.

Или мы можем использовать lapply вместо этого. lapply возвращает list, и, присваивая его столбцам df с помощью df[] <- lapply(), нам не нужно конвертировать. (А поскольку lapply не выполняет преобразование матрицы, по умолчанию он знает, как применить функцию к каждому столбцу.)

df[] <- lapply(df, function(x) ifelse(x > 2, x - 2, 0))

В качестве примечания, df <- cbind(a,b) %>% as.data.frame() - более сложный способ написания df <- data.frame(a, b)

0 голосов
/ 09 ноября 2018

Использование apply

a <- seq(1,5)
b <- seq(0,4)
df <- cbind(a,b) %>% as.data.frame()

new_matrix <- apply(df, MARGIN=2,function(i)ifelse(i >2, i-2,0)) 
new_matrix
###if you want it to return a tibble/df
new_tibble <- apply(df, MARGIN=2,function(i)ifelse(i >2, i-2,0)) %>% as_tibble()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...