2017-07-20 22 views
2

ここでは、 "未定義の列を選択"エラーが発生しています。完全開示:私はRに比較的新しいです。Rでマージを使用して2つの集約を結合

私がする必要があるのは、シリアルを2つの部分に分け> 6 & = 6文字に分割することです。ここで

は、Excelでの作業その一例です:

Child Serial Cost 
N1647961  64.58 

式:=SUMIF(B:B,G98,D:D)+SUMIF(B:B,LEFT(G98,6),D:D)

私が上で、この式を実行するために、独自の子雑誌のリストを作成しました。 B:Bはバニラserial numberある

G98column Dcostで、子のシリアルです。最初に、一致するシリアルの子コストを合計し、その子シリアルの左の6桁を取得し、関連する親コストを合計します。それから、その子供を育てるためのすべての費用がかかります。

「> 6」は「子シリアル」であり、「= 6」は「親シリアル」であるため、親は多くの子を持つことができます。 「子供」は最初の6の後の文字によって区別されます。「123456」は親、「789」は子供です。

df1 <- subset(dBase, nchar(dBase$Serial) = 6) 
df2 <- subset(dBase, nchar(dBase$Serial) > 6) 

ここで私は、各df1a/B

df1a <- aggregate(df1$process_cost, 
       list(serial1 = df1$Serial), 
       FUN = sum) 

df2a <- aggregate(df2$process_cost, 
       list(serial2 = df2$Serial), 
       FUN = sum) 
ここまで

作品における親&子シリアルあたりのコストを集計しています。

ここで、これらのコストをdf2aに「マージ」しようとしています。そのため、すべての費用を親に負担させてから、すべての費用を子供に配分して合計して親子ペアごとにコストが表示されます。次に、このdf3をメインのdf(またはこの例ではdfを使用しているdBase)にマージし、メインファイルに表示するためのコストを整理しました。

問題ここでは、「未定義の列を選択しました」というエラーが表示されます。私はこれを完全に難しくしていますか?

df3 <- merge(df2a, 
      df1a[,c(df1a$serial1, df1a$x)], 
      by = substr(df2a$serial2,1, 6)) 

サンプル:ここでは、例えば両親をdisectできるようにしたいです123456とそれを子供のコストとマッチさせれば、ここでは10なので、総費用は11であり、987654では22となる。親は、 "123456-789"、 "123456-333"、 "123456-114"というように、複数の子を持つことができます。 (例を明確にするためにダッシュを追加)。

serial <- c('123456','987654', '000001', '000002', '123456789', '987654321', '0000', '000002345') 
costs <- c(1, 2, 3, 4, 10, 20, 30, 40) 

df <- data.frame(serial, costs) 

    serial costs 
1 123456  1 
2 987654  2 
3 000001  3 
4 000002  4 
5 123456789 10 
6 987654321 20 
7 0000
8 000002345 40 
+1

申し訳ありませんが、例を追加しましたが、 "="は6、親は "> 6"は子です。 –

+0

私はちょうど混乱の魔法使いですか?ハ!はい、私はこのSOの投稿のためにすべてを "df"に変更しました。 "123456"& "789"の子はサンプルに使用されたばかりです。実際のシリアルは複数の文字(「D12945」など)です。これはデータ型の問題でしょうか?シリアルのtypeof =文字 –

+0

編集のためのThx!文字はprobではありません。 by節はprobであり、式ではなく列名のみを含むことができます。 –

答えて

1

私はこれがあなたが望む出力だと思います。

最初のステップは、それぞれの親のためのユニークな値を持つことになります列parentを作成することですdata.table

library(data.table) 

setDT(df) 
df[, parent := substr(serial, 1, 6)] 
df[, child := substr(serial, 7, 1000000000)] 
df[, total_cost := sum(costs), by = parent] 

を使用します。 2番目の手順では、child列が作成されます。これは、実行する必要がない場合があります。最後のステップでは、すべての費用をparentで合計します。

結果:

#  serial costs parent child total_cost 
# 1: 123456  1 123456    11 
# 2: 987654  2 987654    22 
# 3: 000001  3 000001    33 
# 4: 000002  4 000002    44 
# 5: 123456789 10 123456 789   11 
# 6: 987654321 20 987654 321   22 
# 7: 0000
# 8: 000002345 40 000002 345   44 

あなたはそれぞれの親のためのユニークなコストが必要な場合は、unique(df[, .(parent, total_cost)])を使用しています。使用

# parent total_cost 
# 1: 123456   11 
# 2: 987654   22 
# 3: 000001   33 
# 4: 000002   44 
+0

わずかな問題ですが、total_costはすべて同じ値を表示しています。これは、親ごとではなくdf全体を合計していると思います。ですから、私が一意にすると(df $ total_cost)、それはちょうど1つの値を示します。 –

+0

実際のdfではなく実際の例で動作する理由を理解しようとしています –

1

は、したがって、上記のコードで問題の束がありますが、(あなたは2つのDFSをマージしているとき)Rdf1a[,c(df1a$serial1, df1a$x)]が何であるかを理解していないので、あなたがundefined columnsエラーを取得する理由があります。代わりにdf1a[,c("serial1", "x")]を使用できます。これはこの特定のエラーを解決しますが、もっと問題があるので(特にby引数で)コードが機能しません。

aggregateby引数を使用することをお勧めします。

> aggregate(costs~substr(df$serial,1, 6), sum, data=df) 
    substr(df$serial, 1, 6) costs 
1     000001 33 
2     000002 44 
3     123456 11 
4     987654 22 

Rでこれを行うにはあまりにも多くの方法があり、それらのほとんどは、あなたがおよそaggregateを尋ねたので、(のようなdata.tableまたはgroup_bymutatedplyrで)、しかし、私はそれにこだわってる方が効率的です。

+0

@RYodaあなたは絶対に正しいです!私はそれを完全に逃した、私はOPが望んだものを得るためにコードを更新しています。 –

+1

解決策のためのThx - 間違いなく最も短い解決策(1ライナー:-) –

+0

申し訳ありませんが、私は十分な説明を書いていないと思います。親は複数の子を持つことができます。したがって、 "123456"親は "123456-789"、 "123456-333"、 "123456-114"などに入ることができます。 –

0

だけdata.framedata.tableない - あなたはすでに@EricWattによって答えを見つけることができます):

group costs 
1 000001 33 
2 000002 44 
3 123456 11 
4 987654 22 

df$group <- substr(df$serial, 1, 6) 
aggregate(costs ~ group, df, sum) 

結果は、それがすべて再現可能にするために必要なあなたの質問のコード部分:

serial <- c('123456','987654', '000001', '000002', '123456789', '987654321', '0000', '000002345') 
costs <- c(1, 2, 3, 4, 10, 20, 30, 40) 
df <- data.frame(serial, costs, stringsAsFactors = FALSE) 
+0

親子ペアごとの合計コストは可能ですか?したがって、親A12345に子A12345-111、 '... -112'、 '...- 113'などがある場合は、別の方法で目標を説明することができれば、その子供を作るために費やされたすべての費用を追跡することです。 –

+0

複数のデータでグループ化する。フレーム列は 'res < - aggregate(costs〜group + serial、df、sum)'を使います。 'res [res $ group!= res $ serial、]'で親のみの行だけをフィルタリングする必要があります。 –

関連する問題