2017-02-14 1 views
4

Мне нужно создать таблицу из исходной таблицы (оба ниже).Создайте новую дублируемую таблицу из другого, добавив новые значения из оригиналов, используя R

В исходной таблице мы имеем семейства A и B, а члены каждого семейства обозначены столбцом PESS. Члены каждой семьи, которые являются бенефициарами, отмечены номером 1 в колонке BEN. Из этой таблицы мне нужно создать новую таблицу, в которой у вас должно быть еще 2 столбца. Взяв семью A в качестве примера, члены 1 и 4 являются бенефициарами. Затем семейство A должно быть удвоено на две группы с одним бенефициаром за раз (столбец I_BPC_FAM2). Столбец FAM2 указывает группы.

Приведенный ниже код, я генерирую новую таблицу, однако отсутствует колонка I_BPC_FAM2. Проблема должна быть решена в R.

Возможно ли завершить этот код, чтобы попасть в итоговый стол?

library(tidyverse) 
tabela<-data.frame(FAM=c("A","A","A","A","B","B","B"), PESS=c(1,2,3,4,1,2,3),BEN=c(1,0,0,1,0,0,1)) 
tabela1<- summarise(group_by(tabela,FAM),contador=sum(BEN),cont=n()) #faz a tabela com contadores 

tab2<-NULL 
for(i in 1:length(tabela1$FAM)){ 
    x<-as.numeric(tabela1[i,"contador"]) 
    j<-as.numeric(tabela1[i,"cont"]) 
    for(l in 1:x){ 
     for(k in 1:j){ 
     tab<-data.frame(tabela1[i,"FAM"],PESS=as.numeric(k),FAM2=as.numeric(l)) 
     tab2<-rbind(tab2,tab) 
     final<-merge(tab2,tabela,by=c("FAM","PESS")) 
     final <- final[order(final$FAM, final$FAM2), ] 
     } 
    } 
} 

Оригинальная таблица:

> tabela 
    FAM PESS BEN 
1 A 1 1 
2 A 2 0 
3 A 3 0 
4 A 4 1 
5 B 1 0 
6 B 2 0 
7 B 3 1 

Таблица порождена мой код

> final 
    FAM PESS FAM2 BEN 
1 A 1 1 1 
3 A 2 1 0 
5 A 3 1 0 
7 A 4 1 1 
2 A 1 2 1 
4 A 2 2 0 
6 A 3 2 0 
8 A 4 2 1 
9 B 1 1 0 
10 B 2 1 0 
11 B 3 1 1 

Таблица Мне нужно создать

FAM PESS FAM2 BEN I_BPC_FAM2 
1 A 1 1 1   1 
3 A 2 1 0   0 
5 A 3 1 0   0 
7 A 4 1 1   0 
2 A 1 2 1   0 
4 A 2 2 0   0 
6 A 3 2 0   0 
8 A 4 2 1   1 
9 B 1 1 0   0 
10 B 2 1 0   0 
11 B 3 1 1   1 

Спасибо!

ответ

2

Вот альтернативный способ:

table <-data.frame(FAM=c("A","A","A","A","B","B","B"), 
        PESS=c(1,2,3,4,1,2,3), 
        BEN=c(1,0,0,1,0,0,1)) 

Создать уникальный идентификатор для каждого наблюдения:

table %<>% mutate(unique_id = row_number()) 

Подгруппа групп уникальных семейств нт, чтобы получить:

ben <- 
    table %>% 
    filter(BEN == 1) %>% 
    mutate(FAM2 = unique_id) %>% 
    select(FAM2, FAM) 

> ben 
    FAM2 FAM 
1 1 A 
2 4 A 
3 7 B 

Merge и сравнить идентификаторы:

new_table<- merge(ben, table, by = "FAM") %>% 
      mutate(I_BPC_FAM2 = as.integer(unique_id == FAM2)) %>% 
      select(-unique_id) 

В результате получается:

new_table 
> new_table 
    FAM FAM2 PESS BEN I_BPC_FAM2 
1 A 1 1 1   1 
2 A 1 2 0   0 
3 A 1 3 0   0 
4 A 1 4 1   0 
5 A 4 1 1   0 
6 A 4 2 0   0 
7 A 4 3 0   0 
8 A 4 4 1   1 
9 B 7 1 0   0 
10 B 7 2 0   0 
11 B 7 3 1   1 

Вы можете превратить новые идентификаторы семьи затем, при необходимости, с:

> new_table %>% mutate(FAM2 = as.integer(as.factor(FAM2))) 
    FAM FAM2 PESS BEN I_BPC_FAM2 
1 A 1 1 1   1 
2 A 1 2 0   0 
3 A 1 3 0   0 
4 A 1 4 1   0 
5 A 2 1 1   0 
6 A 2 2 0   0 
7 A 2 3 0   0 
8 A 2 4 1   1 
9 B 3 1 0   0 
10 B 3 2 0   0 
11 B 3 3 1   1 
0

Это должно помочь. Возможно, можно объединить некоторые команды, но я старался быть максимально аналитичным, а также избегать использования для циклов. Запускайте прикованные команды шаг за шагом, чтобы увидеть, как это работает.

library(dplyr) 

# original dataset 
dt <- data.frame(FAM=c("A","A","A","A","B","B","B"), PESS=c(1,2,3,4,1,2,3),BEN=c(1,0,0,1,0,0,1)) 

# create multiple rows of FAM based on how many 1s they have in column BEN 
dt %>% 
    group_by(FAM) %>% 
    mutate(sum_BEN = sum(BEN)) %>% 
    group_by(FAM, PESS) %>% 
    do(data.frame(., FAM2=seq(1,.$sum_BEN))) %>% 
    select(-sum_BEN) %>% 
    ungroup() %>% 
    arrange(FAM, FAM2) %>% 
    print() -> tbl1 

# # A tibble: 11 × 4 
#  FAM PESS BEN FAM2 
# <fctr> <dbl> <dbl> <int> 
# 1  A  1  1  1 
# 2  A  2  0  1 
# 3  A  3  0  1 
# 4  A  4  1  1 
# 5  A  1  1  2 
# 6  A  2  0  2 
# 7  A  3  0  2 
# 8  A  4  1  2 
# 9  B  1  0  1 
# 10  B  2  0  1 
# 11  B  3  1  1 


# keep the relevant rows of FAM to put 1 for I_BPC_FAM2 
dt %>% 
    arrange(FAM, PESS) %>% 
    group_by(FAM) %>% 
    mutate(cumsum_BEN = cumsum(BEN)) %>% 
    ungroup() %>% 
    distinct(FAM, BEN, cumsum_BEN, .keep_all = T) %>% 
    filter(BEN != 0) %>% 
    mutate(I_BPC_FAM2 = 1) %>% 
    rename(FAM2 = cumsum_BEN) %>% 
    print() -> tbl2 

# # A tibble: 3 × 5 
#  FAM PESS BEN FAM2 I_BPC_FAM2 
# <fctr> <dbl> <dbl> <dbl>  <dbl> 
# 1  A  1  1  1   1 
# 2  A  4  1  2   1 
# 3  B  3  1  1   1 


# join tables 
tbl1 %>% 
    left_join(tbl2, by=c("FAM","PESS","BEN","FAM2")) %>% 
    mutate(I_BPC_FAM2 = coalesce(I_BPC_FAM2, 0)) %>% 
    arrange(FAM, FAM2) 

# # A tibble: 11 × 5 
#  FAM PESS BEN FAM2 I_BPC_FAM2 
# <fctr> <dbl> <dbl> <dbl>  <dbl> 
# 1  A  1  1  1   1 
# 2  A  2  0  1   0 
# 3  A  3  0  1   0 
# 4  A  4  1  1   0 
# 5  A  1  1  2   0 
# 6  A  2  0  2   0 
# 7  A  3  0  2   0 
# 8  A  4  1  2   1 
# 9  B  1  0  1   0 
# 10  B  2  0  1   0 
# 11  B  3  1  1   1 
0

Здесь основание R решение с использованием раскола применить методику сочетают с split, lapply и do.call/rbind.

# construct of data.frames, one for each family 
myList <- lapply(split(df, df$FAM), function(i) { 
    bens <- which(i$BEN == 1) # get the benefit indices 
    rows <- nrow(i) # store the number of rows 
    i <- i[rep(seq_len(rows), length(bens)),] # grow data.frame for each benefit 
    i$I_BPC_FAM2 <- 0 # initialize variable 
    i$I_BPC_FAM2[bens + (rows * (seq_along(bens)-1))] <- 1 fill in indicator 
    i # return new data.frame 
}) 

Теперь, вы можете поместить список вместе с

do.call(rbind, myList) 
     FAM PESS BEN I_BPC_FAM2 
A.1  A 1 1   1 
A.2  A 2 0   0 
A.3  A 3 0   0 
A.4  A 4 1   0 
A.1.1 A 1 1   0 
A.2.1 A 2 0   0 
A.3.1 A 3 0   0 
A.4.1 A 4 1   1 
B.5  B 1 0   0 
B.6  B 2 0   0 
B.7  B 3 1   1 
1

Код Николая, я бы чанг е эта часть:

ben <- table %>% 
    filter(BEN == 1) %>% 
    mutate(ID = unique_id) 

    ben %<>% 
    group_by(FAM) %>% 
    mutate(FAM2=cumsum(BEN)) %>% 
    select(ID,FAM2,FAM) 


new_table<- merge(ben, table, by = "FAM") %>% 
    mutate(I_BPC_FAM2 = as.integer(unique_id == ID)) %>% 
    select(-unique_id,-ID) 

какие результаты в этом:

> new_table 
    FAM FAM2 PESS BEN I_BPC_FAM2 
1 A 1 1 1   1 
2 A 1 2 0   0 
3 A 1 3 0   0 
4 A 1 4 1   0 
5 A 2 1 1   0 
6 A 2 2 0   0 
7 A 2 3 0   0 
8 A 2 4 1   1 
9 B 1 1 0   0 
10 B 1 2 0   0 
11 B 1 3 1   1 

Теперь у нас есть FAM2 с правильными номерами семей , которые могут быть практичным с функцией макс()