我有一组对象,让我们说ID为'A'到'J'。我有两个数据帧,看起来如下(你可以看到,第二个数据帧是对称的):
df1 <- data.frame(ID = LETTERS[1:5], Var = c(9,13,15,11,28))
df2 <- as.data.frame(matrix(data = c(NA,42,83,74,84,42,NA,26,69,9,83,26,NA,67,95,74,69,67,NA,6,84,9,95,6,NA), ncol = 5, nrow = 5, dimnames = list(df1$ID, df1$ID)))
例如,取对象'B'和'E'。我想知道:13 + 28(来自df1
)是否小于9(来自df2
)?我想知道所有对象的对象。输出应为
(a)结构类似于df2
和
(b)“TRUE”值的数量。
大多数时候我只需要结果(b),但有时我也需要(a)。因此,如果(b)可以在没有(a)的情况下计算,并且如果这将显着更快,那么我想要两种算法以便选择合适的算法,这取决于我需要回答特定问题的输出。
我正在比较大约2000个对象,因此算法应该相当快。到目前为止,我只能用两个嵌套的for
- 循环来实现它,这非常慢。我敢打赌,有一种更好的方法可以做到这一点,也许可以利用矢量化。
目前的情况如下:
df3 <- as.data.frame(matrix(data = NA, ncol = nrow(df1), nrow = nrow(df1),
dimnames = list(df1$ID, df1$ID)))
for (i in 2:nrow(df3)){
for (j in 1:(i-1)){
sum.val <- df1[df1$ID == rownames(df3)[i], "Var"] + df1[df1$ID == names(df3)[j], "Var"]
df3[i,j] <- sum.val <= df2[i,j]
}
}
#
答案 0 :(得分:3)
这是你想要的吗?
df3 <- outer(df1$Var, df1$Var, "+")
df3
df4 <- df3 < df2
df4
sum(df4, na.rm = TRUE)
答案 1 :(得分:1)
这是一种方法......
# Get row and column indices
ind <- t( combn( df1$ID , 2 ) )
# Get totals
tot <- with( df1 , Var[ match( ind[,1] , ID ) ] + Var[ match( ind[,2] , ID ) ] )
# Make df2 a matrix
m <- as.matrix( df2 )
# Total number of values is simply
sum( m[ ind ] > tot )
#[1] 7
# Find which values in upper triangle part of the matrix exceed those from df1 (1 = TRUE)
m[upper.tri(m)] <- m[ ind ] > tot
# A B C D E
#A NA 1 1 1 0
#B 42 NA 1 0 1
#C 83 26 NA 1 1
#D 74 69 67 NA 0
#E 84 9 95 6 NA
答案 2 :(得分:1)
这将做你想要的。
# Generate the data
df1 <- data.frame(ID = LETTERS[1:5], Var = c(9,13,15,11,28))
df2 <- as.data.frame(matrix(data = c(NA,42,83,74,84,42,NA,26,
69,9,83,26,NA,67,95,74,69,
67,NA,6,84,9,95,6,NA),
ncol = 5, nrow = 5,
dimnames = list(df1$ID, df1$ID)))
# Define a pairwise comparison index matrix using 'combn'
idx <- combn(nrow(df1), 2)
# Create a results matrix
res <- matrix(NA, ncol = ncol(df2), nrow = nrow(df2))
# Loop through 'idx' for each possible comparison (without repeats)
for(i in 1:ncol(idx)){
logiTest <- (df1$Var[idx[1,i]] + df1$Var[idx[2,i]]) < df2[idx[1,i], idx[2,i]]
res[idx[1,i], idx[2, i]] <- logiTest
res[idx[2,i], idx[1, i]] <- logiTest
}
# Count the number of 'true' comparisons
nTrues <- sum(res, na.rm = TRUE)/2
代码只是使用成对比较索引(idx)来定义df1和df2中的哪些元素将在'for循环'的每次迭代中使用。然后,它使用相同的索引来定义'res'矩阵中要写入逻辑测试的答案的位置。
N.B。如果df1和df2中的元素顺序不相同,则此代码将被分解。在这种情况下,使用实际字母来定义要比较的值是合适的。