2016-09-22 1 views
1

Я пытаюсь проверить каждую строку в моей таблице data.table, если есть определенные элементы (которые я объявляю как 1, если есть). Если есть, я хотел бы вывести новый столбец, который показывает значение (вероятность того, что элемент происходит), ссылающийся на другую таблицу данных.Как использовать apply вместо for-loop для проверки каждого столбца в каждой строке

Это является входным

structure(list(A = c(0L, 0L, 0L, 0L, 0L), B = c(0L, 0L, 0L, 0L, 
0L), C = c(1L, 0L, 1L, 1L, 1L), D = c(0L, 1L, 0L, 0L, 1L)), .Names = c("A", 
"B", "C", "D"), class = "data.frame", row.names = c(NA, -5L)) 

В таблицах, которые я использовал для ссылки, чтобы получить вероятности

Таблица Pyxixj

A B C D 
A 0 0 0 0 
B 0 0 0 0 
C 0 0 0 0.001804403 
D 0 0 0.001804403 0 

Таблица Pyxi

A 0 
B 0 
C 0.00086701 
D 0.000250439 

Это выход

A B C D prob 
1 0 0 1 0 0.00086701 
2 0 0 0 1 0.000250439 
3 0 0 1 0 0.00086701 
4 0 0 1 0 0.00086701 
5 0 0 1 1 0.001804403 

Я сделал это с помощью для цикла ниже, но это занимает 6hrs, чтобы работать около 1 миллиона строк.

for (i in 1:nrow(cnts2)) 
{ 
    if ((rowSums(cnts2 == "1", na.rm = TRUE) == 1)[i]) 
    { 
     cnts2$prob[i] <- Pyxi[colnames(cnts2)[which(cnts2[i, ] == 1)]] 
    } 
    else 
    { 
     cnts2$prob[i] <- Pyxixj[colnames(cnts2)[which(cnts2[i, ] == 1)][1], colnames(cnts2)[which(cnts2[i, ] == 1)][2]] 
    } 
} 

пытался apply, но я понял его еще.

+3

Не могли бы вы использовать 'dput' на этих подмножествах' 'Pyxixj' и Pyxi' только, чтобы сделать его легче воспроизвести их? –

+1

Данные для тех, кто это хочет 'cnts2 <-matrix (c (0,0,1,0, 0,0,0,1, 0,0,1,0, 0,0,1,0, 0) , 0,1,1), nrow = 5, ncol = 4, byrow = TRUE) colnames (cnts2) <- c ("A", "B", "C", "D") cnts2 <-as .data.frame (cnts2) Pyxixj <-matrix (c (0,0,0,0, 0,0,0,0, 0,0,0,0,001804403, 0,0,0,001804403,0), nlow = 4, ncol = 4, byrow = TRUE) colnames (Pyxixj) <- c («A», «B», «C», «D») rownames (Pyxixj) <- c («A», «B», «C», «D») Pyxi <-matrix (c (0,0,0,00086701,0,000250439), nrow = 4) rownames (Pyxi) <- c ("A", "B" , "C", "D") ' – MorganBall

+0

Вы пытались параллельно работать с ForEach? – MorganBall

ответ

0

Вот решение, которое будет быстрее, но может потребовать больше бара, так как оно создаст несколько очень длинных кадров данных. Я создал другой фреймплей Pyxixj, так как мое решение не требует другой таблицы.

Ключ к этому решению меняет свой фрейм данных cnts2 в форму, где вероятности могут быть оставлены объединены на, и, таким образом удаляя потребность в циклах или lapply

library(dplyr);library(tidyr) 
#probability data frame note use of X1 
Pyxixj <- data.frame(X1=c("A", "B", "C", "D"), 
      matrix(data=sample(1:100, 16, replace=TRUE)/100, nrow= 4)) %>% 
    setNames(c("X1", "A", "B", "C", "D")) 


#Restructure the initial data frame 
probmerge <-cnts2 %>%mutate(rowid= 1:nrow(.)) %>% 
    gather(., key=column, value=yesno,-rowid) %>% 
    filter(yesno==1) %>% group_by(rowid) %>% 
    mutate(order=make.names(cumsum(yesno))) %>% 
    spread(key=order, value=column) %>% 
    mutate(X2=ifelse(is.na(X2),X1,X2)) %>%ungroup 


#Gather your probability dataframe 
Pyxixj <-Pyxixj %>% gather(key="X2", value=prob,-X1) 

#join the two new dataframes 
probmerge<-left_join(probmerge, Pyxixj, by=c("X1", "X2")) 

#bind onto the orignial dataframe 
cnts2 <- bind_cols(cnts2, select(probmerge, prob)) 
+0

Эй, это сработало отлично, теперь Мне просто нужно получить таблицу вероятности Pyxixj в сочетании справа. Попробуем, как быстро это произойдет позже. Благодаря! – user3231924

+0

Если вы сделаете симметричную матрицу, где AA - вероятность просто A, она будет работать. Или просто создайте матрицу из трех столбцов с начала, где столбцы, первая буква, вторая буква, вероятность. –

0

Вы можете удалить внешний вид окна, чтобы таблица Pyxi от для цикла к циклу через более быстро

Это делает использование векторизации R «ы применения функции при поиске до Pyxi

if (rowSums(cnts2 == "1", na.rm = TRUE) == 1) 
    { 
     cnts2$probs <- (Pyxi[rownames(Pyxi)=="A"]*cnts2$A 
        + Pyxi[rownames(Pyxi)=="B"]*cnts2$B 
        + Pyxi[rownames(Pyxi)=="C"]*cnts2$C 
        + Pyxi[rownames(Pyxi)=="D"]*cnts2$D) 
    } 

Затем сделайте петлю только, где количество строк составляет> 1

for (i in 1:nrow(cnts2)) 
{ 
    if ((rowSums(cnts2 == "1", na.rm = TRUE) > 1)[i]) 
    {cnts2$prob[i] <- Pyxixj[colnames(cnts2)[which(cnts2[i, ] == 1)][1], 
    colnames(cnts2)[which(cnts2[i, ] == 1)][2]] 
    } 
} 
Смежные вопросы