2017-10-10 2 views
0

J'ai une trame de deux données, disons 'df1' et 'df2'. DF1 a la colonne suivante:Comment fusionner plusieurs données avec des noms de colonnes différents

Date 

et DF2 a les colonnes suivantes:

Date.1, USD.Price, Date.2, EUR.Price, Date.3, JPY.Price, Date.4, INR.Price 

où la date, jour1, Date.2, Date.3, sujet.4 ... est en format de date.

Maintenant, je veux fusionner jour1, USD.Price avec DF1 en fonction de DF1 $ Date et DF2 $ Date.2 comme:

df3 = merge(df1, df2[,1:2], by.x = "Date", by.y = "Date.1", all = TRUE) 

Ensuite,

df4 = merge(df3, df2[,3:4], by.x = "Date", by.y = "Date.2", all = TRUE) 

Là encore,

df5 = merge(df4, df2[,5:6], by.x = "Date", by.y = "Date.3", all = TRUE) 

De plus,

df6 = merge(df5, df2[,7:8], by.x = "Date", by.y = "Date.4", all = TRUE) 

et ainsi de suite pour toutes les 1000 telles colonnes.

Par exemple, disons, j'ai une trame de données suivante:

DF1:

Date 
2009-10-13 
2009-10-14 
2009-10-16 
2009-10-18 
2009-10-19 
2009-10-20 
2009-10-21 
2009-10-22 

et DF2:

Date.1  USD.Price Date.2  EUR.Price  Date.3  JPY.Price  Date.4   INR.Price  
2009-10-13 21.6  NA   NA   NA   NA   NA     NA 
2009-10-14 21.9  2009-10-14 78.2   NA   NA   NA     NA 
2009-10-16 22.0  2009-10-16 78.5   NA    NA  2009-10-16   12.2 
NA   NA   2009-10-18 78.9   2009-10-18 32.1  2009-10-18    12.4 
NA   NA   NA   NA   2009-10-19 32.6  2009-10-19    12.2 

Ensuite, la sortie doit être:

Date   USD.Price EUR.Price JPY.Price INR.Price 
2009-10-13  21.6   NA   NA   NA 
2009-10-14  21.9   78.2   NA   NA 
2009-10-16  22.0   78.5   NA   NA 
2009-10-18  NA   78.9   32.1   12.4 
2009-10-19  NA   NA   32.6   12.2 

J'ai quelques re Conférence: How can I merge multiple dataframes with the same column names?

Mais dans mes noms de colonnes de cas sont différents comme jour1, Date.2, Date.3 etc ...

Quelqu'un peut-il s'il vous plaît aidez-moi comment faire pour environ 1000 colonnes aa faire comme ci-dessus n'est pas extensible pour de nombreuses colonnes?

Merci

Répondre

0

Peut-être que cette boucle pourrait vous aider:

for(n in 1:999){ 
    assign(paste('df',n+2,sep = ''), 
     merge(get(paste('df',n,sep = '')), get(paste('df',n+1,sep = ''))[,n:n+1], 
       by.x = 'Date', by.y = paste('Date',n,sep = '.'), all = TRUE), 
     envir = .GlobalEnv) 
} 
1

Vous pouvez essayer une fonction récursive (une fonction qui appelle elle-même).

Il prend deux data.frames et un index de colonne. Il fusionne le data.frames basé sur la première colonne de df1 et la première colonne de df2 qui est sous-classée en utilisant le idx. Ensuite, il s'appelle en utilisant le nouveau data.frame dfx et df2 tandis que idx est inférieur au nombre de colonnes en df2 - 1.

merge_df <- function(df1, df2, idx) { 

    dfx <- merge(df1, df2[, idx:(idx + 1)], by.x = names(df1)[1], 
       by.y = names(df2)[idx]) 

    if (idx < ncol(df2) - 1) { 
    return(merge_df(dfx, df2, idx + 2)) 
    } else { 
    return(dfx) 
    } 
} 

Vous pouvez l'utiliser comme ceci:

df1 <- data.frame(id = 1:10) 
df2 <- data.frame(id1 = 1:10, 
        test1 = letters[1:10], 
        id2 = 1:10, 
        test2 = LETTERS[1:10]) 


df <- merge_df(df1, df2, 1) 

Cela se traduirait par ceci:

head(df, 10) 
    id test1 test2 
1 1  a  A 
2 2  b  B 
3 3  c  C 
4 4  d  D 
5 5  e  E 
6 6  f  F 
7 7  g  G 
8 8  h  H 
9 9  i  I 
10 10  j  J 
1

Vous pouvez le faire ...

datecols <- grep("Date", names(df)) #get date columns 

dfDates <- apply(df[,datecols], 1, function(x) x[!is.na(x)][1]) #vector of dates 

df2 <- cbind(Date=dfDates, df[,-datecols]) #bind dates to non-date columns 

df2 
     Date USD.Price EUR.Price JPY.Price INR.Price 
1 2009-10-13  21.6  NA  NA  NA 
2 2009-10-14  21.9  78.2  NA  NA 
3 2009-10-16  22.0  78.5  NA  12.2 
4 2009-10-18  NA  78.9  32.1  12.4 
5 2009-10-19  NA  NA  32.6  12.2 
0

Un efficace façon de le faire en utilisant sqldf Je pense.

# Changing column names in df2 for convenience 
names(df2) <- c("Date1", "USD_Price", "Date2", "EUR_Price", "Date3", "JPY_Price", "Date4", "INR_Price") 

library(sqldf) 
sqldf({" 
    SELECT D1.Date, D2.USD_Price, D2.EUR_Price, D2.JPY_Price, D2.INR_Price FROM df1 AS D1 
    INNER JOIN df2 AS D2 
    ON D1.Date IN (D2.Date1, D2.Date2, D2.Date3, D2.Date4) 
"}) 

#  Date USD_Price EUR_Price JPY_Price INR_Price 
#1 2009-10-13  21.6  NA  NA  NA 
#2 2009-10-14  21.9  78.2  NA  NA 
#3 2009-10-16  22.0  78.5  NA  12.2 
#4 2009-10-18  NA  78.9  32.1  12.4 
#5 2009-10-19  NA  NA  32.6  12.2 
0

Voici une manière tidyverse en utilisant votre exemple df1 et df2 avec les colonnes de date traitées avec lubridate:

library(tidyr) 
library(dplyr) 
library(lubridate) 

# reformat df2 
df2bis <- 
    df2 %>% 
    gather(key = "tmp_key", 
     value = "Date", 
     starts_with("Date"), 
     na.rm = TRUE) %>% 
    select(-tmp_key) %>% 
    distinct() 

# and merge with df1 
df <- inner_join(df1, df2bis)