具有以下数据集:
test <- data.frame(name= c("A", "B", "C", "D", "E"), v1 = c(2, 4, 1, 1, 2), v2 = c(3, 4, 2, 1, 5))
name v1 v2
A 2 3
B 4 4
C 1 2
D 1 1
E 2 5
我想测试参与者/节点主导性的概念,这意味着对于每一行/条目,我都想查看它是否在数据集中具有最高的价值。例如,对于v1和v2,B均高于A,C和D。因此,它“支配”所有其他行。例如,E仅高于A,C和D,因此它占据了这3行。
从数学上讲,我要搜索的是i >= j, for v1_i >= v1_j and v2_i >= v2_j.
按列进行排列或排序不起作用,因为它并没有真正显示出一行将如何强加另一行,因为它首先按一列然后按另一列进行排序。
编辑:只需添加一个示例,最终输出将是:
B dominates A, C, D
E dominates A, D, C
C dominates D
A dominates C, D
它的外观并不重要。如果它是有向网络/矩阵或带有所有字母的变量的表的形式。
答案 0 :(得分:2)
我有办法,希望对您有所帮助:)
c$v3= rowSums(x = c[,-1])
c = c[order(c$v3,decreasing = T),]
k = length(c$name)
for (i in 1:k ) {
if (i == k) {
}else {
a = c$name[i+1:k]
a = as.character(a[!is.na(a)])
b = c$name[i]
b = as.character(b[!is.na(b)])
cat(b,"greater than ", a,"\n",sep=" ")
}
}
所以您的输出将是
B greater than E A C D
E greater than A C D
A greater than C D
C greater than D
答案 1 :(得分:2)
for
循环在 R 中非常效率低。请避免它们!
您可以使用apply
来完成此操作:
# Names column
names = c("A", "B", "C", "D", "E")
# Dataframe
test <- data.frame(name= names, v1 = c(2, 4, 1, 1, 2), v2 = c(3, 4, 2, 1, 5))
# Display function
findLowerValues <- function(row, test, names) {
rep <- test$v1 <= row["v1"] & test$v2 <= row["v2"] & test$name != row["name"]
cat(row["name"], 'dominates', names[rep], "\n")
}
# Apply the display function
# axis : row
# Extra args: the full dataset and names
apply(test, 1, findLowerValues, test=test, names=names)
# A dominates C D
# B dominates A C D
# C dominates D
# D dominates
# E dominates A C D
# NULL
答案 2 :(得分:1)
这是一个建议。这可能不是最优雅的解决方案。
我们可以有一个函数compare
,该函数检查一个字母是否主导另一个字母(除非它是相同的字母),然后使用两个嵌套的sapply
。
my_letters <- c("A", "B", "C", "D", "E")
test <- data.frame(name= my_letters, v1 = c(2, 4, 1, 1, 2), v2 = c(3, 4, 2, 1, 5))
get_row<-function(letter){
test[test$name==letter,2:ncol(test)]
}
compare<-function(letter,i){
if(letter!=i){
if(!sum(get_row(letter) < get_row(i))){
return(i)
}
}
}
result <- sapply(my_letters, function(let) unlist(sapply(my_letters, compare, letter=let)))
结果列表:
$A
C D
"C" "D"
$B
A C D
"A" "C" "D"
$C
D
"D"
$D
NULL
$E
A C D
"A" "C" "D"
答案 3 :(得分:1)
我们首先将每一行split
放入行列表,然后将其传递给mapply
,rep
将每一行nrow(test)
遍历一次,并将它们与整个数据帧{{1 }},然后选择所有值都大于该行的test
。因为这也将使行与自身匹配,所以我们使用name
删除那些setdiff
值。
name
数据
mapply(function(x, y) setdiff(
test$name[rowSums(x[rep(1, nrow(test)),] >= test[-1]) == ncol(test) - 1], y),
split(test[-1], test$name), test$name)
#$A
#[1] "C" "D"
#$B
#[1] "A" "C" "D"
#$C
#[1] "D"
#$D
#character(0)
#$E
#[1] "A" "C" "D"
答案 4 :(得分:1)
如果您不介意data.table
解决方案,则可能使用非等额联接,如下所示:
library(data.table)
setDT(test)
test[test, on=.(v1<=v1, v2<=v2), .(actor=i.name, node=x.name), by=.EACHI, allow.cartesian=TRUE][
actor!=node, .(actor, node)]
输出:
actor node
1: A C
2: A D
3: B A
4: B C
5: B D
6: C D
7: E A
8: E C
9: E D