按R中的多个条件排列

Arrange by multiple conditions in R

具有以下数据集:

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

我想测试一个 actor/node 支配的概念,这意味着对于每个 row/entry 我想看看它是否在数据集中具有最高值。例如,对于 v1 和 v2,B 都高于 A、C 和 D。所以它 "dominates" 所有其他行。例如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

它看起来如何并不重要。如果它的形式是定向 network/matrix 或带有所有字母的变量的 table。

这是一个建议。这可能不是最优雅的解决方案。 我们可以有一个函数 compare 检查一个字母是否支配另一个字母(除非是相同的字母),然后使用两个嵌套的 sapplys.

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" 

我找到了出路希望这对你有帮助:)

 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 

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

我们首先将每一行 split 放入行列表并将其传递给 mapplyrep 将每一行吃 nrow(test) 次,将它们与整个数据帧进行比较 test 和 select 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"

数据

test <- data.frame(name= c("A", "B", "C", "D", "E"), v1 = c(2, 4, 1, 1, 2),
                   v2 = c(3, 4, 2, 1, 5), stringsAsFactors = FALSE)

如果您不介意 data.table 解决方案,可以使用 non-equi 连接,如下所示:

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