Динамически подмножество и мутирование data.table? - PullRequest
0 голосов
/ 09 марта 2020

У меня есть 2 отдельных DF, я хочу изменить 2 новых столбца в dat2 ('Avg_of_nonNA' и 'Cols', чтобы отслеживать, какой столбец он использует) на основе столбцов без NA в dat1. Мне нужно взять подмножество dat2, потому что матрица плотная, а dat1 - разреженная (поэтому я могу воспользоваться преимуществами разреженности). Единственный способ сопоставить столбцы - сопоставить общие элементы в именах: (0-1,1-2,2-3,3-4) в моем случае. Остальные имена столбцов gibberi sh. Это требует разделения строк и сопоставления - вызывает много проблем, потому что я не могу связать вещи вместе, потому что каждая строка имеет различную комбинацию столбцов для усреднения (фиктивный пример упрощен). У меня есть рабочее решение, но оно мучительно медленно в моих рядах 1M +. Вот это решение:

Я ищу способ избавиться от l oop. Любые предложения?

for (z in 1:5) {
  relevant_cols=dat1[z,] %>%
    select_if(~!all(is.na(.))) %>%
    names %>% strsplit(.,'_') %>% map(.,2) %>% unlist()
  id=dat1[z,'ID']$`ID`
  dat2[`ID`== id,`:=`(Avg_of_nonNA = (mean(as.numeric(.SD))),Cols=paste0(relevant_cols,collapse='/')), .SDcols=names(dat2) %like% paste0(relevant_cols,collapse='|')]
}
Данные ниже
> dat1
   ID gjfkg_0-1_fkjdk_fjdkd jdfsje_1-2_fhks_ejfskj dfjs_2-3_vjskf_wqew gdlkrzc_3-4_rjrkj Avg_of_nonNA_otherDT
1:  1                  2.23                   1.37                  NA                NA                  1.5
2:  2                  1.98                     NA                  NA             1.760                  6.5
3:  3                    NA                   4.45               9.350             3.320                 11.0
4:  4                    NA                     NA               6.642             2.019                 15.5
5:  5                    NA                   3.21               3.677                NA                 18.5
> dat2
   ID ewrwer_0-1_iopi_opop erewtt_1-2_rueiwu_vcvbc erewr_2-3_iirew_rewr mnmn_3-4_cxzxzc_gjd
1:  1                    1                       2                    3                   4
2:  2                    5                       6                    7                   8
3:  3                    9                      10                   11                  12
4:  4                   13                      14                   15                  16
5:  5                   17                      18                   19                  20


dput(dat1)
        structure(list(ID = 1:5, `gjfkg_0-1_fkjdk_fjdkd` = c(2.23, 1.98, 
        NA, NA, NA), `jdfsje_1-2_fhks_ejfskj` = c(1.37, NA, 4.45, NA, 
        3.21), `dfjs_2-3_vjskf_wqew` = c(NA, NA, 9.35, 6.642, 3.677), 
            `gdlkrzc_3-4_rjrkj` = c(NA, 1.76, 3.32, 2.019, NA)), row.names = c(NA, -5L), class = c("data.table", 
        "data.frame"))
dput(dat2)
        structure(list(ID = 1:5, `ewrwer_0-1_iopi_opop` = c(1L, 5L, 9L, 
        13L, 17L), `erewtt_1-2_rueiwu_vcvbc` = c(2L, 6L, 10L, 14L, 18L
        ), `erewr_2-3_iirew_rewr` = c(3L, 7L, 11L, 15L, 19L), `mnmn_3-4_cxzxzc_gjd` = c(4L, 
        8L, 12L, 16L, 20L)), row.names = c(NA, -5L), class = c("data.table", 
        "data.frame"))

Ожидаемый результат: enter image description here

1 Ответ

0 голосов
/ 10 марта 2020

Вот вариант:

setDT(dat1)
setDT(dat2)
nm <- sapply(strsplit(names(dat1[, -"ID"]), "_"), `[[`, 2L)
dat2[, c("Avg_of_nonNA_otherDT", "Cols") := {
    nas <- is.na(dat1[,-"ID"])

    m <- col(nas)
    m[] <- nm[m]
    m[nas] <- ""

    .(rowMeans(.SD * NA^nas, na.rm=TRUE), 
        gsub("\\s+", "/", trimws(do.call(paste, as.data.frame(m)))))
}, .SDcols=-"ID"]

вывод:

   ID ewrwer_0-1_iopi_opop erewtt_1-2_rueiwu_vcvbc erewr_2-3_iirew_rewr mnmn_3-4_cxzxzc_gjd Avg_of_nonNA_otherDT        Cols
1:  1                    1                       2                    3                   4                  1.5     0-1/1-2
2:  2                    5                       6                    7                   8                  6.5     0-1/3-4
3:  3                    9                      10                   11                  12                 11.0 1-2/2-3/3-4
4:  4                   13                      14                   15                  16                 15.5     2-3/3-4
5:  5                   17                      18                   19                  20                 18.5     1-2/2-3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...