【问题标题】:R - cumulative count over multiple columns, by factorR - 多列的累积计数,按因子
【发布时间】:2014-05-15 14:46:06
【问题描述】:

我有一个简化后的数据集,如下所示:

YEAR = c(2009,2009,2009,2009,2009,2009,2009,2010,2010,2010,2010,2010,2010,2010)
FROM = c("A","C","B","D","B","A","C","A","C","B","A","D","B","A")
TO = c("B","D","C","A","D","C","B","B","A","D","D","C","A","D")
DATA = data.frame(YEAR,FROM,TO)

YEAR    FROM    TO
2009    A       B
2009    C       D
2009    B       C
2009    D       A
2009    B       D
2009    A       C
2009    C       B
2010    A       B
2010    C       A
2010    B       D
2010    A       D
2010    D       C
2010    B       A
2010    A       D

我想要的是两个额外的列,比如说 OCC_FROM 和 OCC_TO,这是按 YEAR 表示的前行中 FROM 和 TO 列中出现的累积计数。像这样:

YEAR    FROM    TO  OCC_FROM    OCC_TO
2009    A       B   0           0
2009    C       D   0           0
2009    B       C   1           1
2009    C       A   2           1
2009    B       D   2           1
2009    A       C   2           3
2009    C       B   4           3
2010    A       B   0           0
2010    C       A   0           1
2010    B       D   1           0
2010    A       B   2           2
2010    D       C   1           1
2010    B       A   3           3
2010    A       D   4           2

在Cumulative count in R 的帮助下,我设法制作的是这个,这显然不是我想要的,因为它没有考虑到 YEAR:

DATA$OCC_FROM = sapply(1:length(DATA$FROM),function(i)sum(DATA$FROM[i]==DATA$FROM[1:i]))+sapply(1:length(DATA$FROM),function(i)sum(DATA$FROM[i]==DATA$TO[1:i]))-1
DATA$OCC_TO = sapply(1:length(DATA$TO),function(i)sum(DATA$TO[i]==DATA$FROM[1:i]))+sapply(1:length(DATA$TO),function(i)sum(DATA$TO[i]==DATA$TO[1:i]))-1

YEAR    FROM    TO  OCC_FROM    OCC_TO
2009    A       B   0           0
2009    C       D   0           0
2009    B       C   1           1
2009    C       A   2           1
2009    B       D   2           1
2009    A       C   2           3
2009    C       B   4           3
2010    A       B   3           4
2010    C       A   5           4
2010    B       D   5           2
2010    A       B   5           6
2010    D       C   3           6
2010    B       A   7           6
2010    A       D   7           4

编辑:我还希望能够像以前一样按 YEAR 根据 FROM 和 TO 累计对两列求和。为简单起见,我将使用 OCC_FROM 和 OCC_TO。像这样:

YEAR    FROM    TO  OCC_FROM    OCC_TO    TOTAL_FROM    TOTAL_TO
2009    A       B   0           0         0             0
2009    C       D   0           0         0             0
2009    B       C   1           1         0             0
2009    C       A   2           1         1             0
2009    B       D   2           1         1             0
2009    A       C   2           3         1             3
2009    C       B   4           3         6             3
2010    A       B   0           0         0             0
2010    C       A   0           1         0             0
2010    B       D   1           0         0             0
2010    A       B   2           2         1             1
2010    D       C   1           1         0             0
2010    B       A   3           3         3             3
2010    A       D   4           2         6             1

【问题讨论】:

    标签: r


    【解决方案1】:

    你可以试试

    prevCount <- function(x) {
       eq <- outer(x,x,"==")
       eq <- eq & upper.tri(eq)
       eqInt <- ifelse(eq, 1, 0)
       return(apply(eqInt,2,sum))
    }
    DATA$OCC_FROM <- ave(DATA$FROM, DATA$YEAR, FUN=prevCount )
    

    prevCount 是一个函数,它在一年内返回每个相同元素之前的元素数。然后,ave 电话每年都会应用这个。

    汇总评论中的更正,我们得到

    ord <- order(c(1:nrow(DATA), 1:nrow(data)))
    targets <- c(data$FROM, data$TO)[ord]
    yr <- c(data$YEAR, data$YEAR)[ord]
    res <- ave(targets, yr, FUN=prevCount)
    data$occ_from <- res[seq(1, length(res), 2)]
    data$occ_to <- res[seq(2, length(res), 2)]
    

    另外,prevCount 函数可以简化为:

    prevCount <- function(x) {ave(x==x, x, FUN=cumsum)}
    

    【讨论】:

    • 产生错误:“Math.factor(X[[1L]], ...) 中的错误:cumsum 对因子没有意义”
    • 对不起 - 误读了这个问题。我现在已经编辑它以将因子更改为先前实例的整数计数。但是,它不会同时考虑两个目标列。我需要考虑应该怎么做
    • 为了处理两个目标列(TO 和 FROM),我实际上将它们合并。 ord &lt;- order(c(1:nrow(DATA), 1:nrow(DATA))); targets &lt;- c(data$FROM, data$TO)[ord]; yr &lt;- c(data$YEAR, data$YEAR)[ord]; res &lt;- ave(targets, yr, FUN=prevCOUNT) 然后data$occ_from &lt;- res[seq(along=res, by=2)]; data$occ_to &lt;- res[seq(along=res, by=2)+1]
    • 将第一个seq改为seq(1, length(res),2),第二个改为seq(2,length(res), 2)
    • 如果with(DATA, aggregate(SENT, list(FROM, TO, YEAR), sum))不是你想要的,那么你需要举个例子
    【解决方案2】:
    # Your data - this is not the data at the top of your question but from your 
    # solution  [the 'from' and 'to' don't correspond exactly between your question 
    # and solution]
    
    YEAR <- c(2009,2009,2009,2009,2009,2009,2009,2010,2010,2010,2010,2010,2010,2010)
    FROM <- c("A","C","B","C","B","A","C","A","C","B","A","D","B","A")
    TO <- c( "B","D","C","A","D","C","B","B","A","D","B","C","A","D")
    mydf <- data.frame(YEAR,FROM,TO)
    names(mydf) <- tolower(names(mydf))
    
    #---------------------------------------------------
    # Function to get cumulative sum across columns by group
    f <- function(from , to){
            # combine the columns 'from' and 'to' alternately
            l <- c(rbind(from , to))
    
            # Get and sum duplicate values
            dup <- duplicated(l)
            sums <- ave(dup , l , FUN= cumsum)
    
            # Reshape data & output
            out <- t(matrix(sums ,2))
            colnames(out) <- c("occ_from","occ_to")
            out
          }
    
    # Not considering year 
    f(mydf$from , mydf$to)  
    # (data.frame(mydf , f(mydf$from , mydf$to) )
    
    # Calculate by year
    s <- split(mydf , mydf$year)
    d <- do.call(rbind,lapply(s,function(i) f(i[,"from"],i[,"to"])))
    (mydf <- data.frame(mydf , d , row.names=NULL))
    

    【讨论】:

      猜你喜欢
      • 2012-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-19
      • 2021-09-14
      • 1970-01-01
      • 2021-03-19
      • 2019-04-24
      相关资源
      最近更新 更多