Выполнение действий над списком

#r

#r

Вопрос:

У меня есть список фреймов данных, все из которых содержат числовые данные. Как бы я изменил внутренние data.frames таким образом, чтобы значения NA = 0 и что угодно > или = 1 равнялись 1. В основном, преобразовать в data.frames из нуля и единицы.

Краткий пример.

 x <- list()
x$a <- data.frame(c(NA, NA, 7, 7, NA), c(1,1,NA,NA,NA))
x$b <- data.frame(c(NA, NA, 7, 7, NA), c(1,1,NA,NA,NA))
x$c <- data.frame(c(NA, NA, 7, 7, NA), c(1,1,NA,NA,NA))
  

В общем, если бы я выполнял только одно, я бы сделал что-то вроде:

 x$a[x$a >= 1] <- 1
x[is.na(x$a)] <- 0
  

Теперь, как мне применить это ко всему списку?

ОБНОВЛЕНИЕ: Кто-нибудь хочет добавить решение с помощью ldply() для пущей убедительности?

Ответ №1:

Вероятно, есть более короткое / эффективное решение, но это работает:

 lapply(x, function(y) {y[y >= 1] <- 1; y[is.na(y)] <- 0; y})
  

Комментарии:

1. В списке из 5 фреймов данных, каждый из которых содержит 10 000 строк, это решение стоит на первом месте (10 повторений занимают 0,13 с) (затем решение Чейза (0,31 с), а затем Рамната (2,3 с)).

Ответ №2:

Nest применяется в lapply:

 lapply(x, function(x) 
    apply(x, 2, function(y) ifelse(is.na(y), 0, ifelse(y >= 1, 1, y))
    )
)
  

Ответ №3:

Вот еще один действительно сложный способ сделать это. Это работает путем первой замены всех NAS на 0, а затем выбора минимального числа и 1. Это просто для иллюстрации и развлечения, и НЕ рекомендуется, поскольку это кошмарный код для поддержки!

 lapply(lapply(x, function(y) replace(y, is.na(y), 0)), sapply, pmin, 1)
  

Комментарии:

1. Я подумал о подобном решении, но оно не даст правильных ответов, если есть отрицательные числа, и OP хотел сохранить их такими, какими они были.

2. @Джошуа. Вы правы. Я отредактировал решение, чтобы учесть это поведение