5

私の問題は、ここに投稿されたものと非常によく似ています。

違いは、競合する列を知っていたのに対し、どの列が競合するかを事前に知ることができない汎用メソッドが必要であることです。

例:

TABLE1
Date             Time    ColumnA    ColumnB
01/01/2013      08:00      10         30
01/01/2013      08:30      15         25
01/01/2013      09:00      20         20
02/01/2013      08:00      25         15
02/01/2013      08:30      30         10
02/01/2013      09:00      35         5

TABLE2
Date           ColumnA    ColumnB    ColumnC
01/01/2013      100        300         1
02/01/2013      200        400         2

テーブル 2 には日付しかないため、時間に関係なく日付に一致するテーブル A のすべてのフィールドに適用されます。

マージで競合する列を合計して 1 にしたいと思います。結果は次のようになります。

TABLE3
Date             Time    ColumnA    ColumnB    ColumnC
01/01/2013      08:00      110         330        1
01/01/2013      08:30      115         325        1
01/01/2013      09:00      120         320        1
02/01/2013      08:00      225         415        2
02/01/2013      08:30      230         410        2
02/01/2013      09:00      235         405        2

現時点では、私の標準マージは、「ColumnA.x」、「ColumnA.y」、「ColumnB.x」、「ColumnB.y」の重複列を作成するだけです。

どんな助けでも大歓迎です

4

3 に答える 3

4

私の理解が正しければ、マージする列と保持する列を除いて、各テーブルに存在する列を知る必要のない柔軟な方法が必要です。これは最も洗練されたソリューションではないかもしれませんが、正確なニーズを満たす関数の例を次に示します。

merge_Sum <- function(.df1, .df2, .id_Columns, .match_Columns){
    merged_Columns <- unique(c(names(.df1),names(.df2)))
    merged_df1 <- data.frame(matrix(nrow=nrow(.df1), ncol=length(merged_Columns)))
    names(merged_df1) <- merged_Columns
    for (column in merged_Columns){
        if(column %in% .id_Columns | !column %in% names(.df2)){
            merged_df1[, column] <- .df1[, column]
        } else if (!column %in% names(.df1)){
            merged_df1[, column] <- .df2[match(.df1[, .match_Columns],.df2[, .match_Columns]), column]
        } else {
            df1_Values=.df1[, column]
            df2_Values=.df2[match(.df1[, .match_Columns],.df2[, .match_Columns]), column]
            df2_Values[is.na(df2_Values)] <- 0
            merged_df1[, column] <- df1_Values + df2_Values
        }
    }
    return(merged_df1)
}

この関数は、並べ替えのマスターであるテーブル '.df1' があり、'.df1' の 1 つ以上の行と一致する行を持つ 2 番目のテーブル '.df2' からのデータをマージすることを前提としています。マスター テーブル '.df1' から保持する列は配列 '.id_Columns' として受け入れられ、2 つのテーブルをマージするための一致を提供する列は配列 '.match_Columns' として受け入れられます。

あなたの例では、次のように機能します。

merge_Sum(table1, table2, c("Date","Time"), "Date")

#   Date       Time  ColumnA ColumnB ColumnC
# 1 01/01/2013 08:00     110     330       1
# 2 01/01/2013 08:30     115     325       1
# 3 01/01/2013 09:00     120     320       1
# 4 02/01/2013 08:00     225     415       2
# 5 02/01/2013 08:30     230     410       2
# 6 02/01/2013 09:00     235     405       2

平易な言葉で言えば、この関数は最初に一意の列の総数を見つけ、後でマージされたデータを保持するためにマスター テーブル '.df1' の形で空のデータ フレームを作成します。次に、'.id_Columns' について、データが '.df1' から新しいマージされたデータ フレームにコピーされます。他の列の場合、「.df1」に存在するデータは「.df2」の既存のデータに追加され、「.df2」の行は「.match_Columns」に基づいて照合されます

おそらく、似たようなことを行うパッケージがいくつかありますが、それらのほとんどは、既存のすべての列とそれらの処理方法に関する知識を必要とします。前に述べたように、これは最も洗練されたソリューションではありませんが、柔軟で正確です。

更新:元の関数は、table1 と table2 の間の多対 1 の関係を想定しており、OP は多対非の関係の許可も要求しました。コードは更新され、効率はわずかに低下しますが、100% 柔軟なロジックになりました。

于 2013-02-06T16:15:37.710 に答える
3

data.table解決策:

dt1 <- data.table(read.table(header=T, text="Date             Time    ColumnA    ColumnB
01/01/2013      08:00      10         30
01/01/2013      08:30      15         25
01/01/2013      09:00      20         20
02/01/2013      08:00      25         15
02/01/2013      08:30      30         10
02/01/2013      09:00      35         5"))

dt2 <- data.table(read.table(header=T, text="Date           ColumnA    ColumnB    ColumnC
01/01/2013      100        300         1
02/01/2013      200        400         2"))

setkey(dt1, "Date")
setkey(dt2, "Date")
# Note: The ColumnC assignment has to be come before the summing operations
# Else it gives out error (see below)
dt1[dt2, `:=`(ColumnC = i.ColumnC, ColumnA = ColumnA + i.ColumnA, 
                        ColumnB = ColumnB + i.ColumnB)]

#          Date  Time ColumnA ColumnB ColumnC
# 1: 01/01/2013 08:00     110     330       1
# 2: 01/01/2013 08:30     115     325       1
# 3: 01/01/2013 09:00     120     320       1
# 4: 02/01/2013 08:00     225     415       2
# 5: 02/01/2013 08:30     230     410       2
# 6: 02/01/2013 09:00     235     405       2

ColumnC割り当てを右端に配置するとこのエラーがスローされる理由がわかりません。おそらく MatthewDowle がこのエラーの原因を説明できるでしょう。

dt1[dt2, `:=`(ColumnA = ColumnA + i.ColumnA, ColumnB = ColumnB + i.ColumnB, 
                        ColumnC = i.ColumnC)]

Error in `[.data.table`(dt1, dt2, `:=`(ColumnA = ColumnA + i.ColumnA,  : 
  Value of SET_STRING_ELT() must be a 'CHARSXP' not a 'NULL'

v1.8.9 からの更新:

o 新規の追加と既存の列の更新を混合して:=、グループごとに 1 つの () にします。つまり、
DT[,:=(existingCol=...,newCol=...), by=...]
はエラーやセグメンテーション違反なしで機能するようになりました (#2778 および #2528)。再現可能な例で両方を報告してくれた Arun に感謝します。テストが追加されました。

于 2013-02-06T15:14:57.790 に答える