Давайте исправим вашу функцию и поймем, почему она не работает:
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)