【问题标题】:Row-wise expansion of data.frame [duplicate]data.frame的逐行扩展[重复]
【发布时间】:2016-07-28 14:46:18
【问题描述】:

我基本上想做与ddply(df, columns.to.preserve, numcolwise(FUNCTION)相反的事情。

假设我有

d <- data.frame(
  count=c(2,1,3),
  summed.value=c(50,20,30),
  averaged.value=c(35,80,20)
)

      count summed.value averaged.value
1     2           50             35
2     1           20             80
3     3           30             20

我想根据count 列对此data.frame 进行行扩展,同时指定我想对其他列应用哪种操作。 这是我正在寻找的结果:

> d2
  count summed.value averaged.value
1     1           25             35
2     1           25             35
3     1           20             80
4     1           10             20
5     1           10             20
6     1           10             20

dplyr 或其他包中是否有内置函数可以执行此类操作?

编辑:这与De-aggregate / reverse-summarise / expand a dataset in R 问题不同,因为我想更进一步,实际上将不同的函数应用于我希望扩展的表中的列。这篇文章还有更多有用和答案。

【问题讨论】:

  • 扩展data.frame here的一些地方。完成后,只需将summed.value 和count 除以count。

标签: r dplyr


【解决方案1】:

使用dplyr 和tidyr,您可以对summed.value 进行rowwise 转换,它会为每个单元格生成一个列表,然后unnest 该列应该会为您提供所需的内容:

library(dplyr); library(tidyr)
d %>% rowwise() %>% summarise(summed.value = list(rep(summed.value/count, count)), 
                              averaged.value = averaged.value, count = 1) %>% unnest()

# Source: local data frame [6 x 3]

#   averaged.value count summed.value
#            <dbl> <dbl>        <dbl>
# 1             35     1           25
# 2             35     1           25
# 3             80     1           20
# 4             20     1           10
# 5             20     1           10
# 6             20     1           10

另一种方法是使用data.table,可以指定行号为组变量,数据表会自动展开:

library(data.table)
setDT(d)
d[, .(summed.value = rep(summed.value/count, count), averaged.value, count = 1), .(1:nrow(d))]
 [, nrow := NULL][]

#   summed.value averaged.value count
#1:           25             35     1
#2:           25             35     1
#3:           20             80     1
#4:           10             20     1
#5:           10             20     1
#6:           10             20     1

【讨论】:

    【解决方案2】:

    reshape 包中有一个函数untable 用于获取表格的倒数。然后将需要除以count 的变量通过mutate_at(或mutate_each)。 mutate_at 是在 dplyr_0.5.0 中引入的。

    首先是untable:

    library(reshape)
    untable(d, num = d$count)
    
        count summed.value averaged.value
    1       2           50             35
    1.1     2           50             35
    2       1           20             80
    3       3           30             20
    3.1     3           30             20
    3.2     3           30             20
    

    然后mutate_at 用于将summed.value 和count 除以count:

    library(dplyr)
    
    untable(d, num = d$count) %>%
        mutate_at(vars(summed.value, count), funs(./count))
    
      count summed.value averaged.value
    1     1           25             35
    2     1           25             35
    3     1           20             80
    4     1           10             20
    5     1           10             20
    6     1           10             20
    

    【讨论】:

    • mutate_at 来自哪里?它似乎不在plyr 或dplyr 中。另外,你知道为什么untable 不在reshape2 中吗?
    • mutate_at 在当前版本的 dplyr 中。我不知道为什么 untable 没有被带入 reshape2。
    【解决方案3】:

    这是一个既简单又完全矢量化的 base R 方法

    transform(d[rep(1:nrow(d), d$count), ], 
              count = 1, 
              summed.value = summed.value/count)
    #     count summed.value averaged.value
    # 1       1           25             35
    # 1.1     1           25             35
    # 2       1           20             80
    # 3       1           10             20
    # 3.1     1           10             20
    # 3.2     1           10             20
    

    或者类似地,使用data.table

    library(data.table)
    res <- setDT(d)[rep(1:.N, count)][, `:=`(count = 1, summed.value = summed.value / count)]
    res
    #    count summed.value averaged.value
    # 1:     1           25             35
    # 2:     1           25             35
    # 3:     1           20             80
    # 4:     1           10             20
    # 5:     1           10             20
    # 6:     1           10             20 
    

    【讨论】:

      【解决方案4】:

      基本 R 解决方案:它尝试通过 count 列的值复制每一行,然后将 count 和 summed.value 列除以 count。

      mytext <- 'count,summed.value,averaged.value
      2,50,35
      1,20,80
      3,30,20'
      
      mydf <-  read.table(text=mytext,header=T,sep = ",")
      
      mydf <- do.call(rbind,apply(mydf, 1, function(x) {
        tempdf <- t(replicate(x[1],x,simplify = T))
        tempdf[,1] <- tempdf[,1]/x[1]
        tempdf[,2] <- tempdf[,2]/x[1]
        return(data.frame(tempdf))
      }))
      
      count summed.value averaged.value
           1           25             35
           1           25             35
           1           20             80
           1           10             20
           1           10             20
           1           10             20
      

      【讨论】:

        猜你喜欢
        • 2018-11-30
        • 2020-03-21
        • 2012-06-22
        • 2015-05-29
        • 1970-01-01
        • 2016-11-09
        • 1970-01-01
        相关资源
        最近更新 更多