在R中的数据框中有条件地对值进行分组

时间:2016-10-19 14:30:42

标签: r algorithm loops dataframe

同事

我有以下问题。我的数据集如下所示:

Article = c("A","A","A","A","B","B","B","C","C","C","C")
Value = c(1,5,2,1,20,18,5,6,3,31,99)
df = data.frame(Article, Value)

我的目标是将每篇文章的最高价值与每篇文章的最低价值进行详尽匹配(忽略中间价值),例如: 1表示100,2表示99,3表示98等。并为这些匹配分配组。

此数据框的最终结果必须与第一行匹配" A"第二行文章" A",因为第一行的值是1(它是最低的),第二行的值是5(它是最高的)。对于该对,算法必须分配类似的组,例如, " A_1&#34 ;.然后算法查看Article" A"留下并重复分配过程 - 我们只剩下两行,因此它们将它们匹配到" A_2"。

之后,算法跳转到行=" B"等等。

最终结果必须如下:

Group = c("A_1","A_1", "A_2","A_2", "B_1", "B_NA", "B_1", "C_2", "C_1", "C_2", "C_1")
df = data.frame(Article, Value, Group)

我的想法(我不知道如何编码)有点奇怪:

对于文章中的N,我希望对数据帧段进行升序排序(例如,仅对第N条过滤数据帧并对该段进行升序排序)并分配给第一行的组值=" N_1&# 34 ;.然后分配段值的最后一行=" N_1"。接下来,对于尚未在Group变量中指定值的行过滤此段,并重复第一个和最后一个值的赋值。依此类推,直到算法为一个段中的所有行提供组,然后它跳转到N中的另一个值。

有人可以就此问题向我提出建议吗?非常感谢提前

2 个答案:

答案 0 :(得分:1)

如果每个组的value列没有任何重复,则可以使用此工作。

f_lbl <- function(x, i){
    l <- length(x)
    mid <- floor(l/2)
    lbl <- names(ls)[i]
    a <- paste0(lbl, "_" , rep(NA, l))
    a[1:mid] <- paste0(lbl,"_",1:mid)
    a[l:(l-mid+1)] <- paste0(lbl,"_",1:mid)
    return(a[match(x, sort(x))])
}

ls <- with(df, split(Value, Article))
df$Group <- unlist(sapply(seq_along(ls), function(i) f_lbl(ls[[i]],i)))

   # Article Value Group
# 1        A     3   A_2
# 2        A     5   A_1
# 3        A     2   A_2
# 4        A     1   A_1
# 5        B    20   B_1
# 6        B    18  B_NA
# 7        B     5   B_1
# 8        C     6   C_2
# 9        C     3   C_1
# 10       C    31   C_2
# 11       C    99   C_1

答案 1 :(得分:0)

好的,所以你可以这样做:

library(dplyr)
high_and_low <- df %>%
  group_by(Article) %>%
  summarise(high = max(Value),
            low = min(Value))

只是拉出每个块的高值和低值。如果你需要与找到高/低值的行相关的其他信息,那么你也可以得到它。

这会让你更近一点吗?