R在数据框中生成非重复对,避免相同的组成员
R Generate non repeating pairs in data frame, avoiding same group members
所以目的是通过距离来比较每个ID与其他ID。此外,某些 ID 可能因属于同一组而相关,这意味着如果它们相关则无需比较它们。
考虑以下数据框 Df
ID AN AW Group
a white green 1
b black yellow 1
c purple gray 2
d white gray 2
以下代码有助于实现此结果(来自问题:):
ids <- combn(unique(df$ID), 2)
data.frame(df[match(ids[1,], df$ID), ], df[match(ids[2,], df$ID), ])
#ID AN AW ID2 AN2 AW2
a white green b black yellow
a white green c purple gray
a white green d white gray
b black yellow c purple gray
b black yellow d white gray
c purple gray d white gray
我想知道是否可以不计算某些计算以获得此答案:
#ID AN AW Group ID2 AN2 AW2 Group2
a white green 1 c purple gray 2
a white green 1 d white gray 2
b black yellow 1 c purple gray 2
b black yellow 1 d white gray 2
意味着我可以避免这种计算:
#ID AN AW Group ID2 AN2 AW2 Group2
a white green 1 b black yellow 1
c purple gray 2 d white gray 2
如果我比较组,我可以进行子集化,但这意味着更多的计算时间,因为数据框很大,并且组合遵循 n*(n-1)/2
这可能吗?或者我是否必须进行所有组合,然后将同一组之间的比较进行子集化?
如果您可以使用 sql 来执行此操作,那么 g 代表组。
sqldf("select * from f t1 inner join f t2 on t1.g!=t2.g")
这是一个相当冗长的基础 R 解决方案,假设可能有两个以上的组。
# create test data.frame
df <- data.frame(ID=letters[1:4], AN=c("white", "black", "purple", "white"),
AW=c("green", "yellow", "gray", "gray"),
Group=rep(c(1,2),each=2), stringsAsFactors=FALSE)
# split data.frame by group, subset df to needed variables
dfList <- split(df[, c("ID", "Group")], df$Group)
# use combn to get all group-pair combinations
groupPairs <- combn(unique(df$Group), 2)
接下来,我们遍历(通过 sapply
)组的所有成对组合。对于每个组合,我们构建一个 data.frame,它是每个组之间通过 expand.grid
的 ID 的成对组合。从命名列表中提取 ID(使用 [[]]
运算符),dfList 使用它们在 groupPairs[1,i]
和 groupPairs[2,i]
.
中的名称
# get a list of all ID combinations by group combination
myComparisonList <- sapply(1:ncol(groupPairs), function(i) {
expand.grid(dfList[[groupPairs[1,i]]]$ID,
dfList[[groupPairs[2,i]]]$ID,
stringsAsFactors=F)
})
# extract list of combinations to matrix
idsMat <- sapply(myComparisonList, rbind)
# bind comparison pairs together by column
dfDone <- cbind(df[match(idsMat[,1], df$ID), ], df[match(idsMat[,2], df$ID), ])
# differentiate names
names(dfDone) <- paste0(names(dfDone), rep(c(".1", ".2"),
each=length(names(df))))
所以目的是通过距离来比较每个ID与其他ID。此外,某些 ID 可能因属于同一组而相关,这意味着如果它们相关则无需比较它们。
考虑以下数据框 Df
ID AN AW Group
a white green 1
b black yellow 1
c purple gray 2
d white gray 2
以下代码有助于实现此结果(来自问题:
ids <- combn(unique(df$ID), 2)
data.frame(df[match(ids[1,], df$ID), ], df[match(ids[2,], df$ID), ])
#ID AN AW ID2 AN2 AW2
a white green b black yellow
a white green c purple gray
a white green d white gray
b black yellow c purple gray
b black yellow d white gray
c purple gray d white gray
我想知道是否可以不计算某些计算以获得此答案:
#ID AN AW Group ID2 AN2 AW2 Group2
a white green 1 c purple gray 2
a white green 1 d white gray 2
b black yellow 1 c purple gray 2
b black yellow 1 d white gray 2
意味着我可以避免这种计算:
#ID AN AW Group ID2 AN2 AW2 Group2
a white green 1 b black yellow 1
c purple gray 2 d white gray 2
如果我比较组,我可以进行子集化,但这意味着更多的计算时间,因为数据框很大,并且组合遵循 n*(n-1)/2
这可能吗?或者我是否必须进行所有组合,然后将同一组之间的比较进行子集化?
如果您可以使用 sql 来执行此操作,那么 g 代表组。
sqldf("select * from f t1 inner join f t2 on t1.g!=t2.g")
这是一个相当冗长的基础 R 解决方案,假设可能有两个以上的组。
# create test data.frame
df <- data.frame(ID=letters[1:4], AN=c("white", "black", "purple", "white"),
AW=c("green", "yellow", "gray", "gray"),
Group=rep(c(1,2),each=2), stringsAsFactors=FALSE)
# split data.frame by group, subset df to needed variables
dfList <- split(df[, c("ID", "Group")], df$Group)
# use combn to get all group-pair combinations
groupPairs <- combn(unique(df$Group), 2)
接下来,我们遍历(通过 sapply
)组的所有成对组合。对于每个组合,我们构建一个 data.frame,它是每个组之间通过 expand.grid
的 ID 的成对组合。从命名列表中提取 ID(使用 [[]]
运算符),dfList 使用它们在 groupPairs[1,i]
和 groupPairs[2,i]
.
# get a list of all ID combinations by group combination
myComparisonList <- sapply(1:ncol(groupPairs), function(i) {
expand.grid(dfList[[groupPairs[1,i]]]$ID,
dfList[[groupPairs[2,i]]]$ID,
stringsAsFactors=F)
})
# extract list of combinations to matrix
idsMat <- sapply(myComparisonList, rbind)
# bind comparison pairs together by column
dfDone <- cbind(df[match(idsMat[,1], df$ID), ], df[match(idsMat[,2], df$ID), ])
# differentiate names
names(dfDone) <- paste0(names(dfDone), rep(c(".1", ".2"),
each=length(names(df))))