r语言 - 按数据帧中的不同列比较行



我有一个看起来像这样的数据帧:

id   value1  value2   value3   value4
A      14       24       22        9
B      51       25       29       33
C       4       16        8       10
D       1        4        2        4       

现在,我想将该行的每一列与其他行进行比较,以确定每个值较高的行。

因此,例如,对于id D,这将是A,B和C。对于 C,它将是 B,对于 A,它是 B,对于 B 则没有行。

我试图通过循环浏览行并比较每一列来做到这一点,但这需要很多时间。原始数据集有大约 5000 行和 20 列要比较。我相信有办法更有效地做到这一点。感谢您的帮助!

我不知道

一个简单的函数来完成这个任务。这是我会怎么做的。

library(dplyr)
DF <- data.frame(
  id = c("A", "B", "C", "D"),
  value1 = c(14, 51, 4, 1),
  value2 = c(24, 25, 16, 4),
  value3 = c(22, 29, 8, 2),
  value4 = c(9, 33, 10, 4),
  stringsAsFactors = FALSE)
# get the order for each value
tmp <- lapply(select(DF, -id), function(x) DF$id[order(x)]) 
# find a set of "biggers" for each id 
tmp <- lapply(tmp, function(x) data.frame(
    id = rep(x, rev(seq_along(x))-1), 
    bigger = x[lapply(seq_along(x), function(i)
      which(seq_along(x) > i)) %>% unlist()],
    stringsAsFactors = FALSE)) 
# inner_join all, this keeps "biggers" in all columns
out <- NULL
for (v in tmp) {
  if (is.null(out)) {
    out <- v
  } else {
    out <- inner_join(out, v, by = c("id", "bigger"))
  }
}

这可以让您:

out
#  id bigger
#1  D      C
#2  D      A
#3  D      B
#4  C      B
#5  A      B

这是一种以数据框格式返回结果的方法。

library(tidyr)
library(dplyr)
# reshape data to long format
td <- d %>% gather(key, value, value1:value4)
# create a copy w/ different names for merging
td2 <- td %>% select(id2 = id, key, value2 = value)
# full outer join to produce one row per pair of IDs
dd <- merge(td, td2, by = "key", all = TRUE)
# the result
dd %>%
  filter(id != id2) %>% 
  group_by(id, id2) %>%
  summarise(all_less = !any(value >= value2)) %>%
  filter(all_less)

结果(ID 小于 ID2(

     id    id2 all_less
  (fctr) (fctr)    (lgl)
1      A      B     TRUE
2      C      B     TRUE
3      D      A     TRUE
4      D      B     TRUE
5      D      C     TRUE

数据

d <- structure(list(
  id = structure(1:4, .Label = c("A", "B", "C", "D"), class = "factor"), 
  value1 = c(14L, 51L, 4L, 1L), 
  value2 = c(24L, 25L, 16L, 4L), 
  value3 = c(22L, 29L, 8L, 2L), value4 = c(9L, 33L, 10L, 4L)
), 
.Names = c("id", "value1", "value2", "value3", "value4"), 
class = "data.frame", row.names = c(NA, -4L)
)

我认为这很好用:

ind <- which(names(df) == "id")
apply(df[,-ind],1,function(x) df$id[!rowSums(!t(x < t(df[,-ind])))] )
# [[1]]
# [1] "B"
# 
# [[2]]
# character(0)
# 
# [[3]]
# [1] "B"
# 
# [[4]]
# [1] "A" "B" "C"

相关内容

  • 没有找到相关文章

最新更新