4

次の関数を実装する必要があります(理想的にはRまたはSQLで):2つのデータフレームが与えられた場合(ユーザーIDの列があり、残りの列はブール属性です(0または1であることが許可されています))返す必要があります2つの列(useridとcount)を持つ新しいデータフレーム。countは、両方のテーブルの各ユーザーの0と1の一致数です。ユーザーFは、両方のデータフレームで発生することも、1つだけで発生することもあります。この最後のケースでは、そのユーザー数のNAを返す必要があります。私は例を書きます:

DF1
ID c1 c2 c3 c4 c5
1   0  1  0  1  1
10  1  0  1  0  0
5   0  1  1  1  0
20  1  1  0  0  1
3   1  1  0  0  1
6   0  0  1  1  1
71  1  0  1  0  0
15  0  1  1  1  0
80  0  0  0  1  0

DF2  
ID c1 c2 c3 c4 c5
5   1  0  1  1  0
6   0  1  0  0  1
15  1  0  0  1  1
80  1  1  1  0  0
78  1  1  1  0  0
98  0  0  1  1  1
1   0  1  0  0  1
2   1  0  0  1  1
9   0  0  0  1  0

私の関数は次のようなものを返す必要があります:(以下はサブセットです)

DF_Return
ID Count
1    4
2    NA
80   1
20   NA
   .
   .
   .

これを実行するための提案をお願いします。私はSQLの専門家ではありません。

上記で使用した実験を生成するために、コードをRに入れました。

 id1=c(1,10,5,20,3,6,71,15,80)
 c1=c(0,1,0,1,1,0,1,0,0)
 c2=c(1,0,1,1,1,0,0,1,0)
 c3=c(0,1,1,0,0,1,1,1,0)
 c4=c(1,0,1,0,0,1,0,1,1)
 c5=c(1,0,0,1,1,1,0,0,0)
 DF1=data.frame(ID=id1,c1=c1,c2=c2,c3=c3,c4=c4,c5=c5)
 DF2=data.frame(ID=c(5,6,15,80,78,98,1,2,9),c1=c2,c2=c1,c3=c5,c4=c4,c5=c3)

よろしくお願いします。よろしくお願いします!

4

5 に答える 5

3

これがあなたのためのアプローチです。最初の列は比較する列をハードコードしますが、もう1つの列はより一般的で、DF1とDF2の列の数に依存しません。

#Merge together using ALL = TRUE for equivlent of outer join
DF3 <- merge(DF1, DF2, by = "ID", all = TRUE, suffixes= c(".1", ".2"))
#Calculate the rowSums where the same columns match
out1 <- data.frame(ID = DF3[, 1], count = rowSums(DF3[, 2:6] ==  DF3[, 7:ncol(DF3)]))

#Approach that is agnostic to the number of columns you have
library(reshape2)
library(plyr)
DF3.m <- melt(DF3, id.vars = 1)
DF3.m[, c("level", "DF")] <- with(DF3.m, colsplit(variable, "\\.", c("level", "DF")))
out2 <- dcast(data = DF3.m, ID + level ~ DF, value.var="value")
colnames(out)[3:4] <- c("DF1", "DF2")
out2 <- ddply(out, "ID", summarize, count = sum(DF1 == DF2))

#Are they the same?
all.equal(out1, out2)
#[1] TRUE

> head(out1)
  ID count
1  1     4
2  2    NA
3  3    NA
4  5     3
5  6     2
6  9    NA
于 2012-04-13T17:19:10.700 に答える
2
SELECT
  COALESCE(DF1.ID, DF2.ID)  AS ID,
  CASE WHEN DF1.c1 = DF2.c1 THEN 1 ELSE 0 END +
  CASE WHEN DF1.c2 = DF2.c2 THEN 1 ELSE 0 END +
  CASE WHEN DF1.c3 = DF2.c3 THEN 1 ELSE 0 END +
  CASE WHEN DF1.c4 = DF2.c4 THEN 1 ELSE 0 END +
  CASE WHEN DF1.c5 = DF2.c5 THEN 1 ELSE 0 END AS count_of_matches
FROM
  DF1
FULL OUTER JOIN
  DF2
    ON DF1.ID = DF2.ID
于 2012-04-13T16:22:03.477 に答える
2

おそらくもっとエレガントな方法がありますが、これはうまくいきます:

x <- merge(DF1,DF2,by="ID",all=TRUE)
pre <- paste("c",1:5,sep="")
x$Count <- rowSums(x[,paste(pre,"x",sep=".")]==x[,paste(pre,"y",sep=".")])
DF_Return <- x[,c("ID","Count")]
于 2012-04-13T17:18:28.347 に答える
1

safe_full_joinパッケージsafejoinから使用して、== 競合する列の間に適用できます。c*これにより、使用できる論理列を持つ新しいデータフレームが生成 rowSumsされます。

# devtools::install_github("moodymudskipper/safejoin")
library(safejoin)
library(dplyr)

safe_full_join(DF1, DF2, by = "ID", conflict = `==`) %>%
  transmute(ID, count = rowSums(.[-1]))
#    ID count
# 1   1     4
# 2  10    NA
# 3   5     3
# 4  20    NA
# 5   3    NA
# 6   6     2
# 7  71    NA
# 8  15     1
# 9  80     1
# 10 78    NA
# 11 98    NA
# 12  2    NA
# 13  9    NA
于 2019-02-26T00:29:00.610 に答える
0

applyこの関数を使用してこれを処理できます。各行の合計を取得するには、次を使用できます。

sums <- apply(df1[2:ncol(df1)], 1, sum)
cbind(df1[1], sums)

これにより、最初の列を除くすべての合計が返され、それを最初の列にバインドしてIDを取得します。

両方のデータフレームでそれを行うことができます。その後の望ましい動作はよくわかりませんが、merge関数を見てください。

于 2012-04-13T16:12:11.823 に答える