Объединить фреймы данных по точному совпадению столбца - PullRequest
0 голосов
/ 03 октября 2018

Я хотел бы объединить два фрейма данных, где в одном есть больше переменных (столбцов), а в другом - больше наблюдений (строк).Ниже приведен упрощенный пример их настройки:

Фрейм данных 1:

ID      Date         Indicator
12345   01/01/2008   1
54321   12/01/2008   1

Фрейм данных 2:

ID      Date         
12345   01/01/2008   
12345   01/31/2008
12345   02/28/2009
24681   01/01/2008
54321   12/01/2008
54321   12/20/2008

Я хотел бы сделать толькосохраняйте строки, в которых идентификаторы точно совпадают.Например, я хотел бы следующий вывод:

Новый кадр данных:

ID      Date         Indicator     
12345   01/01/2008   1
12345   01/31/2008   NA
12345   02/28/2009   NA
54321   12/01/2008   1
54321   12/20/2008   NA

Я пробовал

new <- merge(df1, df2, all=TRUE)

, но это приводит к объединению ВСЕХ строк,тогда как я хочу только строки из df2 с идентификатором, которые видны в df1.

Любая помощь приветствуется!

Ответы [ 7 ]

0 голосов
/ 03 октября 2018

Если ваш размер данных не слишком велик, вы можете добавить строку, которая фильтрует ваши результаты по df1 $ id.

new <- new[new$id %in% unique(df1$id),]
0 голосов
/ 04 октября 2018

объединение - это то, что вы ищете.Если таблица, которую вы планируете сохранить в качестве справочной, находится слева, то это левое соединение.Пример кода

    df1<-data.frame(ID=c(12345,54321) ,Date  =c('01/01/2008',' 12/01/2008 ')   ,    
     Indicator=c(1,1))

     df2<-data.frame(ID=c(12345,12345,5341) ,Date  =c('01/01/2008',' 12/01/2008 
      ','12/1/2008') )

    merge(df1,df2,by.x = 'ID',by.y='ID')

      ID     Date.x       Indicator       Date.y
      12345 01/01/2008         1    01/01/2008
      12345 01/01/2008         1    12/01/2008 

Таким образом, только строки из df1, присутствующие в df 2, являются частью вывода

0 голосов
/ 03 октября 2018

Вы можете попробовать функцию join () из библиотеки ply.Вам также потребуется дополнительный шаг, чтобы получить именно тот результат, который вам нужен.

library(plyr)

df1

     ID       Date Indicator
1 12345 2020-01-01         1
2 54321 2020-12-01         1

 df2

     ID       Date
1 12345 2020-01-01
2 12345 2020-01-31
3 12345 2020-02-28
4 24681 2020-01-01
5 54321 2020-12-01
6 54321 2020-12-20

# that extra step
df3 <- df2[df2$ID %in% df1$ID,]
df3
     ID       Date
1 12345 2020-01-01
2 12345 2020-01-31
3 12345 2020-02-28
5 54321 2020-12-01
6 54321 2020-12-20

join(df3, df1, by = c("ID", "Date"))
     ID       Date Indicator
1 12345 2020-01-01         1
2 12345 2020-01-31        NA
3 12345 2020-02-28        NA
4 54321 2020-12-01         1
5 54321 2020-12-20        NA
0 голосов
/ 03 октября 2018

Просто попробуйте:

library(dplyr)
df2 %>%
  left_join(df1, by = c("ID", "Date")) %>% # or full_join(df1, by = c("ID", "Date"))
  filter(ID %in% df1$ID) 

Или исходя из того, что вы начали:

merge(df1, df2, all = TRUE) %>% filter(ID %in% df1$ID)
0 голосов
/ 03 октября 2018

Рассмотрим merge с subset:

df3 <- subset(merge(df1, df2, by=c("ID", "Date"), all=TRUE), ID %in% df1$ID)

df3
#      ID       Date Indicator
# 1 12345 01/01/2008         1
# 2 12345 01/31/2008        NA
# 3 12345 02/28/2009        NA
# 5 54321 12/01/2008         1
# 6 54321 12/20/2008        NA

Чтобы сбросить row.names, оберните конструктор data.frame() и укажите аргумент имен строк:

df3 <- data.frame(subset(merge(df1, df2, by=c("ID", "Date"), all=TRUE),
                         ID %in% df1$ID),
                  row.names = NULL)

df3
#      ID       Date Indicator
# 1 12345 01/01/2008         1
# 2 12345 01/31/2008        NA
# 3 12345 02/28/2009        NA
# 4 54321 12/01/2008         1
# 5 54321 12/20/2008        NA
0 голосов
/ 03 октября 2018

Отредактировано на основе комментария s_t:

left_join(df2, df1, by=c("ID", "Date")) %>% filter(ID %in% df1$ID)
0 голосов
/ 03 октября 2018

Вы можете попробовать с dplyr решением:

library(dplyr)
# a right join when you filter Dataframe2 by ID in Dataframe1
Dataframe1 %>% right_join(Dataframe2[Dataframe2$ID %in% Dataframe1$ID,])  

Joining, by = c("ID", "Date")
     ID       Date Indicator
1 12345 01/01/2008         1
2 12345 01/31/2008        NA
3 12345 02/28/2009        NA
4 54321 12/01/2008         1
5 54321 12/20/2008        NA

# clearly you can put it in a data.frame
Dataframe3 <- Dataframe1 %>% right_join(Dataframe2[Dataframe2$ID %in% Dataframe1$ID,], by = 'ID') %>% 
             data.frame()

Так что у вас не будет ID 24681, и у вас будет NA в Indicator там, где это кажется необходимым, то есть когдаDate не хочет этого.


Ваши данные:

Dataframe1 <- read.table(text="ID      Date         Indicator
12345   01/01/2008   1
54321   12/01/2008   1", stringsAsFactors = F, header = T)

Dataframe2 <- read.table(text="ID      Date         
12345   01/01/2008   
12345   01/31/2008
12345   02/28/2009
24681   01/01/2008
54321   12/01/2008
54321   12/20/2008",stringsAsFactors = F, header = T)
...