Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R-从序列数据构建新变量_R_Dataframe_Data.table_Sequence - Fatal编程技术网

R-从序列数据构建新变量

R-从序列数据构建新变量,r,dataframe,data.table,sequence,R,Dataframe,Data.table,Sequence,这是对问题的更新/跟进。答案概述了他们的产品不符合新的要求 我正在寻找一种有效的方法(data.table?)为每个ID构造两个新的度量 措施1和措施2需要满足以下条件: 条件1: 查找三行的序列,其中: 第一个计数>0 第二个'count>1'和 第三个计数==1 措施1的条件2: 获取序列第三行的product中元素的值,这些元素是: 在序列第二行的产品中 不在序列第一行的库存中 措施2的条件2: 获取序列最后一行的product中元素的值,这些元素是: 不在序列第二行的产品中 不

这是对问题的更新/跟进。答案概述了他们的产品不符合新的要求

我正在寻找一种有效的方法(
data.table
?)为每个
ID
构造两个新的度量

措施1和措施2需要满足以下条件:

条件1: 查找三行的序列,其中:

  • 第一个
    计数>0
  • 第二个'count>1'和
  • 第三个
    计数==1
措施1的条件2:

  • 获取序列第三行的
    product
    中元素的值,这些元素是:
  • 在序列第二行的
    产品中
  • 不在序列第一行的
    库存中
措施2的条件2:

  • 获取序列最后一行的
    product
    中元素的值,这些元素是:
  • 不在序列第二行的
    产品中
  • 不在序列第一行的
    库存中
数据:


您将如何编写此代码?

要做到这一点,您需要知道几件事:

  • shift
    用于比较组中的值
  • separate_rows
    函数用于分割字符串以进入标准化数据视图
库(data.table)
dt 1&count.3==1]

dt我不确定高效的标准是什么,但这里有一种使用
embed
tidyverse
风格的方法。它会过滤,所以你的工作越来越少

加载数据和包(注意后面的
setdiff
intersect
来自
dplry

您可以将其转换回最终产品、以前的产品和感兴趣的库存行,以通过添加偏移来确定度量。将它们拆分为单个组件的列表

finalProds <- df1$product[cond1Match + 2] %>%
  strsplit(",")
prevProds <- df1$product[cond1Match + 1] %>%
  strsplit(",")
initialStock <- df1$stock[cond1Match] %>%
  strsplit(",")
这将生成所需的输出,每个ID最多只能有一行。在原始帖子中,您指定要报告所有内容。删除
切片
调用将产生

#>   ID seq1 seq2 seq3 measure1 measure2
#> 1  1    2    3    4        C        E
#> 2  1    6    7    1                  
#> 3  2    1    2    3                  
#> 4  2    3    1    2                 C
#> 5  3    2    3    4        D

如果您希望真正压缩效率,您可以通过将
finalProds
prevProds
initialStock
的定义放在前面而不是将它们分配给变量来获得一些效率。我可以想象,除非你的匹配集真的很大,否则它可以忽略不计

使用
数据的滚动窗口方法。表
j中的基本R代码

library(data.table)
cols <- c("product", "stock")
setDT(df2)[, (cols) := lapply(.SD, function(x) strsplit(as.character(x), split=",")), .SDcols=cols]

ans <- df2[, 
    transpose(lapply(1L:(.N-2L), function(k) {
        if(count[k]>0 && count[k+1L]>1 && count[k+2L]==1) {
            m1 <- setdiff(intersect(product[[k+2L]], product[[k+1L]]), stock[[k]])
            m2 <- setdiff(setdiff(product[[k+2L]], product[[k+1L]]), stock[[k]])
            c(seq1=seqs[k], seq2=seqs[k+1L], seq3=seqs[k+2L],
                measure1=if(length(m1) > 0) paste(m1, collapse=",") else "",
                measure2=if(length(m2) > 0) paste(m2, collapse=",") else "")
        }
    }), ignore.empty=TRUE),
    ID]
setnames(ans, names(ans)[-1L], c(paste0("seq", 1:3), paste0("measure", 1:2)))
ans

这很有趣。滚动窗口是否有效?也就是说,它是否能够很好地扩展到包含500.000多行的数据?我认为您的问题需要滚动窗口。可能还有比这更有效的方法。您可能希望在实际数据集上进行尝试。这种方法适用于模拟数据。但在实际数据(500000多行)中,product和stock列中填充了数百项。因此,当我们分离行时,
dt
变得非常大,我的本地机器(128GB)内存不足。
单独的_行
是否有替代方案?也许是一个
regex
解决方案?好吧,你可以做几件事:1。对数据进行分区,并分块解决问题(也就是说,将其缩小)2。将这些数据放入像BigQuery(又称委托)这样的数据库中,然后使用SQL。3.检查其他一些软件包,例如,回答此处也请参见D3方法:
library(purrr)
library(dplyr)

df1 <- data.frame(ID = c(1,1,1,1,1,1,1,2,2,2,3,3,3,3),
                  seqs = c(1,2,3,4,5,6,7,1,2,3,1,2,3,4),
                  count = c(2,1,3,1,1,2,3,1,2,1,3,1,4,1),
                  product = c("A", "B", "C", "A,C,E", "A,B", 
                              "A,B,C", "D", "A", "B", "A", "A", 
                              "A,B,C", "D", "D"),
                  stock = c("A", "A,B", "A,B,C", "A,B,C,E", "A,B,C,E", 
                            "A,B,C,E", "A,B,C,D,E", "A", "A,B", "A,B", "A", 
                            "A,B,C", "A,B,C,D", "A,B,C,D"),
                  stringsAsFactors = FALSE)
meetsCond1 <- function(rseg) { 

  seg <- rev(rseg)

  all(seg[1] > 0, seg[2] > 1, seg[3] == 1)

}
cond1Match<- embed(df1$count, 3) %>%
  apply(1, meetsCond1) %>%
  which()
finalProds <- df1$product[cond1Match + 2] %>%
  strsplit(",")
prevProds <- df1$product[cond1Match + 1] %>%
  strsplit(",")
initialStock <- df1$stock[cond1Match] %>%
  strsplit(",")
notStock <- map2(finalProds, initialStock, ~.x[!(.x %in% .y)])
data.frame(ID = df1$ID[cond1Match],
           seq1 = df1$seqs[cond1Match], 
           seq2 = df1$seqs[cond1Match + 1],
           seq3 = df1$seqs[cond1Match + 2],
           measure1 = imap_chr(notStock, 
                               ~intersect(.x, prevProds[[.y]]) %>%
                               {if(length(.) == 0) "" else paste(., sep = ",")}

           ),
           measure2 = imap_chr(notStock, 
                               ~setdiff(.x, prevProds[[.y]]) %>%
                               {if(length(.) == 0) "" else paste(., sep = ",")}

           ),
           stringsAsFactors = FALSE
) %>%
  slice(match(unique(ID), ID))
#>   ID seq1 seq2 seq3 measure1 measure2
#> 1  1    2    3    4        C        E
#> 2  1    6    7    1                  
#> 3  2    1    2    3                  
#> 4  2    3    1    2                 C
#> 5  3    2    3    4        D
library(data.table)
cols <- c("product", "stock")
setDT(df2)[, (cols) := lapply(.SD, function(x) strsplit(as.character(x), split=",")), .SDcols=cols]

ans <- df2[, 
    transpose(lapply(1L:(.N-2L), function(k) {
        if(count[k]>0 && count[k+1L]>1 && count[k+2L]==1) {
            m1 <- setdiff(intersect(product[[k+2L]], product[[k+1L]]), stock[[k]])
            m2 <- setdiff(setdiff(product[[k+2L]], product[[k+1L]]), stock[[k]])
            c(seq1=seqs[k], seq2=seqs[k+1L], seq3=seqs[k+2L],
                measure1=if(length(m1) > 0) paste(m1, collapse=",") else "",
                measure2=if(length(m2) > 0) paste(m2, collapse=",") else "")
        }
    }), ignore.empty=TRUE),
    ID]
setnames(ans, names(ans)[-1L], c(paste0("seq", 1:3), paste0("measure", 1:2)))
ans
   ID seq1 seq2 seq3 measure1 measure2
1:  1    2    3    4        C        E
2:  2    1    2    3                  
3:  3    2    3    4        D