【问题标题】:Remove duplicated rows dependend on factor根据因子删除重复行
【发布时间】:2016-02-25 20:54:23
【问题描述】:

我想从按不同因素和条件(例如最高均值或标准差)分层的数据框中删除重复的行。

一些数据,a 是行的因子和 id。

set.seed(13654)
a<- sort(c(1,1,4,1,2,3,2,3,1,5))
b<- matrix(runif(100,min = 6,max = 14),nrow = 10)
c<- data.frame(a,b)  

例如,我想减少平均值最高的行上的最终数据集。

# calculate means per row
gr <- cbind(a,M=rowMeans(c[,-1]))
# get rows stratified by a with highest mean:
gr1 <- aggregate(M~a,gr,which.max)
gr1
  a M
1 1 3
2 2 2
3 3 1
4 4 1
5 5 1

因此,因子级别 1 的第三行,因子级别 2 的第二行,...应该包含在新数据框中。我想避免循环。我尝试的是split 数据然后使用lapply,但到目前为止还没有工作。

cl <- split(c,a)
# this function does not work it will select not the correct rows. 
lapply(cl, "[", gr1, )

我的最终目标是这样的函数:

remove.dupl <- function(data,factor,method=c(highest.mean,highest.sd,lowest.sd,...))

您能否为我的问题提供一些提示或解决方案。按照我的工作流程,我需要一个“操作方法”来正确使用 "[" 和 lapply 从数据框列表中选择不同的行。

【问题讨论】:

    标签: r duplicates


    【解决方案1】:

    试试by()函数:

    set.seed(13654)
    a <- sort(c(1,1,4,1,2,3,2,3,1,5))
    b <- matrix(runif(100,min = 6,max = 14),nrow = 10)
    c <- data.frame(a,b)
    myfun <- function(x) which.max(rowMeans(x))                   # just replicating your example, you could define other functions here
    d <- by(data = c, INDICES = c$a, function(x) x[myfun(x), ])   # use by() to select rows, based on myfun()
    d <- do.call(rbind, d)                                        # turn result of by() function into a data frame
    

    【讨论】:

    • 善用by。加一。
    【解决方案2】:

    使用 data.table 包,我将按如下方式处理它:

    library(data.table)
    # method 1:
    setDT(cc)[, `:=` (rn = 1:.N, wm = which.max(rowMeans(.SD))), a][rn==wm]
    # method 2:
    setDT(cc)[, wm := frank(1/rowMeans(.SD), ties.method="first"), a][wm==1]
    

    给出:

       a        X1        X2        X3        X4        X5        X6        X7        X8       X9       X10 wm rn
    1: 1 13.946254  7.302729  9.406389  8.924367  8.129423 10.174735  6.547805 11.618872 12.84100  9.494790  3  3
    2: 2 13.606555 12.798149 11.261258 12.991822 12.875935 11.199411  8.551149 10.377451 13.63219 13.643163  2  2
    3: 3  6.820769 13.748507 11.630297 11.559873  6.196406  8.925419 11.230415 10.584249 10.41442  6.821673  1  1
    4: 4  8.418767 10.673998  6.693021 11.101287  7.855519  9.106210 12.279536  6.925023  6.92334 10.279204  1  1
    5: 5 11.529072  7.940031 10.746172  8.535466 13.703122 12.294424 11.362498 11.256843 13.95535 13.264835  1  1
    

    在基础 R 中你可以这样做:

    cc$rm <- apply(cc[,-1], 1, mean)
    cc$wm <- ave(cc$rm, cc$a, FUN = function(x) max(x)==x)
    cc[cc$wm == 1,]
    

    给出:

       a        X1        X2        X3        X4        X5        X6        X7        X8       X9       X10        rm wm
    3  1 13.946254  7.302729  9.406389  8.924367  8.129423 10.174735  6.547805 11.618872 12.84100  9.494790  9.838637  1
    6  2 13.606555 12.798149 11.261258 12.991822 12.875935 11.199411  8.551149 10.377451 13.63219 13.643163 12.093708  1
    7  3  6.820769 13.748507 11.630297 11.559873  6.196406  8.925419 11.230415 10.584249 10.41442  6.821673  9.793203  1
    9  4  8.418767 10.673998  6.693021 11.101287  7.855519  9.106210 12.279536  6.925023  6.92334 10.279204  9.025591  1
    10 5 11.529072  7.940031 10.746172  8.535466 13.703122 12.294424 11.362498 11.256843 13.95535 13.264835 11.458781  1
    

    回应您的评论:作为替代方案,您可以在ave 中使用rank 函数:

    # duplicate the row for which 'max(x)==x' for the first group
    cc <- rbind(cc,cc[3,])
    
    cc$wm2 <- ave(cc$rm, cc$a, FUN = function(x) rank(-x, ties.method = "first"))
    cc[cc$wm2 == 1,]
    

    给出:

       a        X1        X2        X3        X4        X5        X6        X7        X8       X9       X10        rm wm wm2
    3  1 13.946254  7.302729  9.406389  8.924367  8.129423 10.174735  6.547805 11.618872 12.84100  9.494790  9.838637  1   1
    6  2 13.606555 12.798149 11.261258 12.991822 12.875935 11.199411  8.551149 10.377451 13.63219 13.643163 12.093708  1   1
    7  3  6.820769 13.748507 11.630297 11.559873  6.196406  8.925419 11.230415 10.584249 10.41442  6.821673  9.793203  1   1
    9  4  8.418767 10.673998  6.693021 11.101287  7.855519  9.106210 12.279536  6.925023  6.92334 10.279204  9.025591  1   1
    10 5 11.529072  7.940031 10.746172  8.535466 13.703122 12.294424 11.362498 11.256843 13.95535 13.264835 11.458781  1   1
    

    注意:我将数据框重命名为 cc,因为最好不要使用函数名作为数据框的名称

    【讨论】:

    • 非常感谢,但我更喜欢基础 R 解决方案。但我牢记这一点。
    • @Jimbou np,还添加了一个替代的基础 R 解决方案
    • 如果您必须删除重复项,您将如何优化您的ave 函数?例如。 max(x)==x 仅返回 TRUE 或多个 TRUE
    • @Jimbou 我已经更新了我的答案。这是你要找的吗?
    猜你喜欢
    • 2019-06-22
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 2017-08-08
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    相关资源
    最近更新 更多