2016-04-13 5 views
3

В моем наборе данных повторяются наблюдения за людьми, которые работают над проектами. Мне нужен фрейм данных с двумя столбцами, которые перечисляют «комбинации» проектов для каждого человека и точки времени. Поясню на примере:Реструктуризация/изменение кадра данных (r)

Это мои данные:

ID Week Project  
01 1  101 
01 1  102 
01 1  103 
01 2  101 
01 2  102 
02 1  101 
02 1  102 
02 2  101 

Person 1 (ID = 1) работал над тремя проектами в неделю 1. Это означает, что существует шесть возможных комбинаций проектов (project_i & project_j) для этого человека, на этой неделе.

Это то, что мне нужно

ID Week Project_i Project_j 
01 1  101  101 
01 1  101  102 
01 1  101  103 
01 1  102  101 
01 1  102  102  
01 1  102  103 
01 1  103  101 
01 1  103  102 
01 1  103  103 
01 2  101  101 
01 2  101  102 
01 2  102  101 
01 2  102  102 
02 1  101  101 
02 1  101  102 
02 1  102  101 
02 1  102  102 
02 2  101  101 

Потеря случаев, которые имеют только один проект в неделю не является проблемой.

Я пробовал базовые r и reshape2 немного, но я не могу понять это.

+0

Прямо сейчас, я не включил тот же идентификатор проекта в той же строке (т.е. 101 101) –

ответ

6

Вот один из способов:

library(data.table) 
setDT(DT) 

DT[, CJ(P1 = Project, P2 = Project)[P1 != P2], by=.(ID, Week)] 

    ID Week P1 P2 
1: 1 1 101 102 
2: 1 1 101 103 
3: 1 1 102 101 
4: 1 1 102 103 
5: 1 1 103 101 
6: 1 1 103 102 
7: 1 2 101 102 
8: 1 2 102 101 
9: 2 1 101 102 
10: 2 1 102 101 

CJ декартова Регистрация двух векторов, принимая все возможные комбинации.

Если вы не хотите, чтобы оба (101,102) и (102,101) использовали P1 > P2 вместо P1 != P2. О, ОП изменил вопрос ... поэтому используйте P1 <= P2.

+0

Это похоже на работу, но г еще работает , Считаете ли вы, что это займет много времени (или вообще возможно) для 2 миллионов наблюдений? –

+1

@HJ_r Это, вероятно, нет. Вам нужно рассмотреть комбинаторную проблему, которую вы пытаетесь решить. Вы можете ввести 'combos = DT [,. (N = .N * (. N-1L)), by =. (ID, Week)]', чтобы увидеть размер проблемы. 'combos [, sum (n)]' будет отображать общее количество строк в результате, а также вы можете посмотреть 'combos [, summary (n)]', 'combos [, hist (n)]' и т. д. – Frank

+0

Спасибо, в итоге ваше решение отлично работало. –

6

Вот решение, которое использует dplyr и tidyr. Ключевой шаг tidyr::complete() в сочетании с dplyr::group_by()

library(dplyr) 
library(tidyr) 

d %>% 
    rename(Project_i = Project) %>% 
    mutate(Project_j = Project_i) %>% 
    group_by(ID, Week) %>% 
    complete(Project_i, Project_j) %>% 
    filter(Project_i != Project_j) 
5

Вот базовый вариант с использованием expand.grid:

do.call(rbind, lapply(split(df, paste(df$ID, df$Week)), function(x){ 
    x2 <- expand.grid(ID = unique(x$ID), 
         Week = unique(x$Week), 
         Project_i = unique(x$Project), 
         Project_j = unique(x$Project)) 
    # omit if 101 102 is different from 102 101; make `<` if 101 101 not possible 
    x2[x2$Project_i <= x2$Project_j,] 
})) 

#  ID Week Project_i Project_j 
# 1 1.1 1 1  101  101 
# 1 1.4 1 1  101  102 
# 1 1.5 1 1  102  102 
# 1 1.7 1 1  101  103 
# 1 1.8 1 1  102  103 
# 1 1.9 1 1  103  103 
# 1 2.1 1 2  101  101 
# 1 2.3 1 2  101  102 
# 1 2.4 1 2  102  102 
# 2 1.1 2 1  101  101 
# 2 1.3 2 1  101  102 
# 2 1.4 2 1  102  102 
# 2 2 2 2  101  101 

 Смежные вопросы

  • Нет связанных вопросов^_^