首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用data.table计算广告牌

用data.table计算广告牌
EN

Stack Overflow用户
提问于 2020-01-07 07:47:55
回答 3查看 219关注 0票数 2

我有一个数据文件,如下所示:

代码语言:javascript
复制
structure(list(ID = c(1, 1, 1, 1, 2, 2, 2, 2), ColA = c(2, 3, 
4, 5, 2, 3, 4, 5), ColB = c(1, 2, 3, 4, 1, 2, 3, 4), ColA_0.2 = c(2, 
3.4, 4.68, 5.936, 2, 3.4, 4.68, 5.936), ColB_0.2 = c(1, 2.2, 
3.44, 4.688, 1, 2.2, 3.44, 4.688)), class = "data.frame", row.names = c(NA, 
-8L))

我需要什么?-对于每个ID,我要计算ColA_adColB_ad。用户将传递一个参数'ad‘。

例如,如果'ad‘为0.2,则计算值为:

  • 第一行--与ColA (即2)
  • 第二行相同--将第二行ColA添加到0.2*第一行ColA_ad (即
  • 行)--将第三行ColA添加到ColA_ad的第二行(即Sum(4,0.2*3.4)=4.68),等等。

对于所有其他列(此处为ColB)也将进行相同的计算,这些列可以在单独的向量中提及。

总结-我将采取0.2倍结转效果的上一个计算行,并添加到新的行。

结果显示在列ColA_adColB_ad中。

由于我的数据集非常大,我正在寻找data.table解决方案。

EN

回答 3

Stack Overflow用户

发布于 2020-01-07 08:39:15

这里是一个基R解,其中应用了线性代数属性来加快迭代计算。

  • basic idea (以id = 1为例)

代码语言:javascript
复制
- you first construct a low triangluar matrix for mapping from `col` to `col_ad`, i.e.,

代码语言:javascript
复制
l <- 0.2**abs(outer(seq(4),seq(4),"-"))
l[upper.tri(l)] <- 0

这给

代码语言:javascript
复制
> l
      [,1] [,2] [,3] [,4]
[1,] 1.000 0.00  0.0    0
[2,] 0.200 1.00  0.0    0
[3,] 0.040 0.20  1.0    0
[4,] 0.008 0.04  0.2    1

  • 然后在列col上使用l,即

代码语言:javascript
复制
> l %*% as.matrix(subset(df,ID == 1)[-1])
      ColA  ColB
[1,] 2.000 1.000
[2,] 3.400 2.200
[3,] 4.680 3.440
[4,] 5.936 4.688

  • code

代码语言:javascript
复制
ad <- 0.2
col_ad <- do.call(rbind,
                  c(make.row.names = F,
                    lapply(split(df,df$ID), 
                           function(x) {
                             l <- ad**abs(outer(seq(nrow(x)),seq(nrow(x)),"-"))
                             l[upper.tri(l)]<- 0
                             `colnames<-`(data.frame(l%*% as.matrix(x[-1])),paste0(names(x[-1]),"_",ad))
                           }
                    )
                  )
)

dfout <- cbind(df,col_ad)

这样的话

代码语言:javascript
复制
> dfout
  ID ColA ColB ColA_0.2 ColB_0.2
1  1    2    1    2.000    1.000
2  1    3    2    3.400    2.200
3  1    4    3    4.680    3.440
4  1    5    4    5.936    4.688
5  2    2    1    2.000    1.000
6  2    3    2    3.400    2.200
7  2    4    3    4.680    3.440
8  2    5    4    5.936    4.688

  • DATA

代码语言:javascript
复制
df <- structure(list(ID = c(1, 1, 1, 1, 2, 2, 2, 2), ColA = c(2, 3, 
                                                              4, 5, 2, 3, 4, 5), ColB = c(1, 2, 3, 4, 1, 2, 3, 4)), class = "data.frame", row.names = c(NA, 
                                                                                                                                                        -8L))
票数 3
EN

Stack Overflow用户

发布于 2020-01-07 08:01:10

非递归选项:

代码语言:javascript
复制
setDT(DT)[, paste0(cols,"_",ad) := { 
    m <- matrix(unlist(shift(ad^(seq_len(.N)-1L), 0L:(.N-1L), fill = 0)), nrow=.N)
    lapply(.SD, function(x) c(m%*%x))
}, by = ID, .SDcols = cols]

另一个递归选项:

代码语言:javascript
复制
library(data.table)
setDT(DT)[, paste0(cols,"_",ad) := {
        a <- 0
        b <- 0
        .SD[, {
            a <- ColA + ad*a        
            b <- ColB + ad*b
            .(a, b)

        }, seq_len(.N)][, (1) := NULL]
    }, 
    by = ID]

产出:

代码语言:javascript
复制
   ID ColA ColB ColA_0.2 ColB_0.2
1:  1    2    1    2.000    1.000
2:  1    3    2    3.400    2.200
3:  1    4    3    4.680    3.440
4:  1    5    4    5.936    4.688
5:  2    2    1    2.000    1.000
6:  2    3    2    3.400    2.200
7:  2    4    3    4.680    3.440
8:  2    5    4    5.936    4.688

数据:

代码语言:javascript
复制
DT <- structure(list(ID = c(1, 1, 1, 1, 2, 2, 2, 2), ColA = c(2, 3, 
    4, 5, 2, 3, 4, 5), ColB = c(1, 2, 3, 4, 1, 2, 3, 4), ColA_0.2 = c(2, 
        3.4, 4.68, 5.936, 2, 3.4, 4.68, 5.936), ColB_0.2 = c(1, 2.2, 
            3.44, 4.688, 1, 2.2, 3.44, 4.688)), class = "data.frame", row.names = c(NA, 
                -8L))
ad <- 0.2
cols <- c("ColA", "ColB")
票数 2
EN

Stack Overflow用户

发布于 2020-01-07 07:59:15

下面是使用data.table使用Reduce的一种方法

代码语言:javascript
复制
#Columns to apply function to
cols <- names(df)[2:3]

#Create a function to apply 
apply_fun <- function(col, ad) {
   Reduce(function(x, y) sum(y, x * ad), col, accumulate = TRUE)
}

library(data.table)
#Convert dataframe to data.table
setDT(df)
#set ad value
ad <- 0.2
#Apply funnction to each columns of cols
df[, (paste(cols, ad, sep =  "_")) := lapply(.SD, apply_fun, ad), .SDcols = cols, by = ID]

df
#   ID ColA ColB ColA_0.2 ColB_0.2
#1:  1    2    1    2.000    1.000
#2:  1    3    2    3.400    2.200
#3:  1    4    3    4.680    3.440
#4:  1    5    4    5.936    4.688
#5:  2    2    1    2.000    1.000
#6:  2    3    2    3.400    2.200
#7:  2    4    3    4.680    3.440
#8:  2    5    4    5.936    4.688
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59624211

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档