4

次の 3 つのデータフレームがあります。

df1 <- data.frame(name=c("John", "Anne", "Christine", "Andy"),
                  age=c(31, 26, 54, 48),
                  height=c(180, 175, 160, 168),
                  group=c("Student",3,5,"Employer"), stringsAsFactors=FALSE)

df2 <- data.frame(name=c("Anne", "Christine"),
                  age=c(26, 54),
                  height=c(175, 160),
                  group=c(3,5),
                  group2=c("Teacher",6), stringsAsFactors=FALSE)

df2 <- data.frame(name=c("Christine"),
                  age=c(54),
                  height=c(160),
                  group=c(5),
                  group2=c(6),
                  group3=c("Scientist"), stringsAsFactors=FALSE)

次の結果が得られるように、それらを組み合わせたいと思います。

df.all <- data.frame(name=c("John", "Anne", "Christine", "Andy"),
                     age=c(31, 26, 54, 48),
                     height=c(180, 175, 160, 168),
                     group=c("Student", "Teacher", "Scientist", "Employer"))

現時点では、私はこのようにしています:

df.all <- merge(merge(df1[,c(1,4)], df2[,c(1,5)], all=TRUE, by="name"),
                df3[,c(1,6)], all=TRUE, by="name")
row.ind <- which(df.all$group %in% c(6,5))
df.all[row.ind, c("group")] <- df.all[row.ind, c("group2")]
row.ind2 <- which(df.all$group2 %in% c(6))
df.all[row.ind2, c("group")] <- df.all[row.ind2, c("group3")]

これは一般化できず、非常に面倒です。merge_allまたはを使用する方法がmerge_recurseあるかもしれません または マージステップ(特に、マージされるデータフレームが2つ以上ある可能性があるため)ですが、方法がわかりません。これら 2 つは正しい結果を生成しません。

df.all <- merge_all(list(df1, df2, df3))
df.all <- merge_recurse(list(df1, df2, df3), by=c("name"))

この問題を解決するためのより一般的でエレガントな方法はありますか?

4

2 に答える 2

5

あなたが最終的に何を求めているかを理解していれば、別の可能なアプローチがあります。(「グループ」列の数値が何であるかは明確ではないため、これがまさにあなたが探しているものかどうかはわかりません。)

Reduce()複数の をマージするために使用しますdata.frame

temp <- Reduce(function(x, y) merge(x, y, all=TRUE), list(df1, df2, df3))
names(temp)[4] <- "group1" # Rename "group" to "group1" for reshaping 
temp
#        name age height   group1  group2    group3
# 1      Andy  48    168 Employer    <NA>      <NA>
# 2      Anne  26    175        3 Teacher      <NA>
# 3 Christine  54    160        5       6 Scientist
# 4      John  31    180  Student    <NA>      <NA>

reshape()データをワイドからロングに再形成するために使用します。

df.all <- reshape(temp, direction = "long", idvar="name", varying=4:6, sep="")
df.all
#                  name age height time     group
# Andy.1           Andy  48    168    1  Employer
# Anne.1           Anne  26    175    1         3
# Christine.1 Christine  54    160    1         5
# John.1           John  31    180    1   Student
# Andy.2           Andy  48    168    2      <NA>
# Anne.2           Anne  26    175    2   Teacher
# Christine.2 Christine  54    160    2         6
# John.2           John  31    180    2      <NA>
# Andy.3           Andy  48    168    3      <NA>
# Anne.3           Anne  26    175    3      <NA>
# Christine.3 Christine  54    160    3 Scientist
# John.3           John  31    180    3      <NA>

as.numeric()が文字を に強制するという事実をNA利用し、値na.omit()を持つすべての行を削除するために使用しNAます。

na.omit(df.all[is.na(as.numeric(df.all$group)), ])
#                  name age height time     group
# Andy.1           Andy  48    168    1  Employer
# John.1           John  31    180    1   Student
# Anne.2           Anne  26    175    2   Teacher
# Christine.3 Christine  54    160    3 Scientist

繰り返しますが、これは問題を過度に一般化する可能性があります。たとえば、他の列に NA 値が存在する可能性がありますが、問題の解決策に導くのに役立つ場合があります。

于 2012-12-14T18:26:28.520 に答える
4

最初のステップは、次のように使用merge_recurseすることall.x = TRUEです。

library(reshape)
merge.all <- merge_recurse(list(df1, df2, df3), all.x = TRUE)
#        name age height    group  group2    group3
# 1      Anne  26    175        3 Teacher      <NA>
# 2 Christine  54    160        5       6 Scientist
# 3      John  31    180  Student    <NA>      <NA>
# 4      Andy  48    168 Employer    <NA>      <NA>

次に、すべての「グループ」列からapply最後の非グループを取得するために使用できます。NA

group.cols <- grep("group", colnames(merge.all))
merge.all <- data.frame(merge.all[-group.cols],
                        group = apply(merge.all[group.cols], 1,
                                      function(x)tail(na.omit(x), 1)))
#        name age height     group
# 1      Anne  26    175   Teacher
# 2 Christine  54    160 Scientist
# 3      John  31    180   Student
# 4      Andy  48    168  Employer
于 2012-12-14T15:18:52.927 に答える