在R

时间:2019-05-23 10:15:45

标签: r sorting dplyr network-analysis

具有以下数据集:

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

它的外观并不重要。如果它是有向网络/矩阵或带有所有字母的变量的表的形式。

5 个答案:

答案 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放入行列表,然后将其传递给mapplyrep将每一行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