Использование функций применения вместо циклов for в R - PullRequest
0 голосов
/ 29 февраля 2020

Я пытался заменить для l oop в своем коде на функцию apply, и я пытался сделать это всеми возможными способами, используя sapply и lapply, apply и mapply, всегда кажется, что это не сработало , оригинальная функция выглядит следующим образом

ds1 <- data.frame(col1 = c(NA, 2), col2 = c("A", "B"))
ds2 <- data.frame(colA = c("A", "B"), colB = c(90, 110))

for(i in 1:nrow(ds1)){
  if(is.na(ds1$col1[i])){
    ds1$col1[i] <- ds2[ds2[,"colA"] == ds1$col2[i], "colB"]
  }
}

Моя последняя попытка с применением семейства выглядит следующим образом

ds1 <- data.frame(col1 = c(NA, 2), col2 = c("A", "B"))
ds2 <- data.frame(colA = c("A", "B"), colB = c(90, 110))

sFunc <- function(x, y, z){
  if(is.na(x)){
    return(z[z[,"colA"] == y, "colB"])
  } else {
    return(x)
  }
}

ds1$col1 <- sapply(ds1$col1, sFunc, ds1$col2, ds2)

, которая возвращает ds2$colB для каждой строки, может кто-нибудь объяснить мне, что Я ошибся по этому поводу?

Ответы [ 2 ]

2 голосов
/ 29 февраля 2020

Объединение было бы полезно здесь. Вы можете сделать это в базе R:

transform(merge(ds1, ds2, by.x = "col2", by.y = "colA"), 
          col1 = ifelse(is.na(col1), colB, col1))[names(ds1)]

#  col1 col2
#1   90    A
#2    2    B

или с помощью dplyr

library(dplyr)

inner_join(ds1, ds2, by = c("col2" = "colA")) %>%
    mutate(col1 = coalesce(col1, colB)) %>%
    select(names(ds1))
2 голосов
/ 29 февраля 2020

sapply повторяется только по первому вектору, который вы передаете. Другие аргументы, которые вы передадите, будут рассматриваться как целые векторы в каждом l oop. Для итерации по m ультратонким векторам необходимо m ultivariate apply, то есть m apply.

sFunc <- function(x, y){
  if(is.na(x)){
    return(ds2[ds2[,"colA"] == y, "colB"])
  } else {
    return(x)
  }
}

mapply(sFunc, ds1$col1, ds1$col2)
#> [1] 90  2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...