tstr在一轮中拆分到不同的列

2024-02-25

我有一个如下表:

myDT <- fread(
  "id,other,strformat,content
 1, other1, A:B,    a1:b1
 2, other2, A:C,    a2:c2
 3, other3, B:A:C,  b3:a3:c3
 4, other4, A:B,    a4:b4
 5, other5, XX:whatever,    xx5:whatever5
")

我想分割content列基于strformat,得到这个:

   id  other   strformat       content    A    B    C   XX  whatever
1:  1 other1         A:B         a1:b1   a1   b1 <NA> <NA>      <NA>
2:  2 other2         A:C         a2:c2   a2 <NA>   c2 <NA>      <NA>
3:  3 other3       B:A:C      b3:a3:c3   a3   b3   c3 <NA>      <NA>
4:  4 other4         A:B         a4:b4   a4   b4 <NA> <NA>      <NA>
5:  5 other5 XX:whatever xx5:whatever5 <NA> <NA> <NA>  xx5 whatever5

我失败了tstrsplit() on by=:

myDT[, unlist(strsplit(strformat,':')):=tstrsplit(content,':'), by=strformat]
# Error in strsplit(strformat, ":") : object 'strformat' not found

所以现在我求助于使用循环:

for (this.format in unique(myDT$strformat)){
  myDT[strformat==this.format, unlist(strsplit(this.format,':')):=tstrsplit(content,':')]
}

它可以完成工作,但我仍然想知道什么是正确的方法by=


因此,我测试了 @akrun 善意建议的 3 个解决方案,并稍加修改。跳过最后一个,因为它对列名进行了硬编码。

# define functions to compare:

require(splitstackshape)
f_csplit <- function(inpDT, col_format='strformat', col_content='content', sep=':'){
  invisible(inpDT[dcast(
    cSplit(inpDT, c(col_format, col_content), sep, "long"), 
    as.formula(paste('id',col_format,sep='~')), 
    value.var=col_content
  ), , on = .(id)])
}

f_lapply_str <- function(inpDT, col_format='strformat', col_content='content', sep=':'){
  invisible(inpDT[dcast(
    inpDT[, unlist(lapply(.SD, strsplit, sep), recursive = FALSE), by = id, .SDcols = 2:3], 
    as.formula(paste('id',col_format,sep='~')),
    value.var=col_content
  ), on = .(id)])
}

require(tidyverse)
f_unnest <- function(inpDT, col_format='strformat', col_content='content', sep=':'){
  invisible(inpDT[dcast(
    unnest(inpDT[, lapply(.SD, tstrsplit, sep),by = id, .SDcols = 2:3]), 
    as.formula(paste('id',col_format,sep='~')), 
    value.var=col_content
  ), on = .(id)])
}

f_cycle <- function(inpDT, col_format='strformat', col_content='content', sep=':'){
  inpDT <- copy(inpDT); # in fact I don't even need to make a copy:
                        # := modifies the original table which is fine for me - 
                        # but for benchmarking let's make a copy  
  for (this.format in unique(inpDT[[col_format]])){
    inpDT[get(col_format)==this.format, unlist(strsplit(this.format,sep)):=tstrsplit(get(col_content),sep)]
  }
  invisible(inpDT)
}

看来解决方案#2(lapply of strsplit, 没有cSplit)和#3(unnest)当表中有任何其他列时,它无法正常工作,只有当我删除“其他”时,它才有效:

myDT[dcast(myDT[, unlist(lapply(.SD, strsplit, ":"), recursive = FALSE), by = id, .SDcols = 2:3], id ~ strformat), on = .(id)]
#      id  other   strformat       content    A    B    C   XX whatever
#   1:  1 other1         A:B         a1:b1    A    B <NA> <NA>     <NA>
#   2:  2 other2         A:C         a2:c2    A <NA>    C <NA>     <NA>
#   3:  3 other3       B:A:C      b3:a3:c3    A    B    C <NA>     <NA>
#   4:  4 other4         A:B         a4:b4    A    B <NA> <NA>     <NA>
#   5:  5 other5 XX:whatever xx5:whatever5 <NA> <NA> <NA>   XX whatever

myDT[dcast(unnest(myDT[, lapply(.SD, tstrsplit, ":"),by = id, .SDcols = 2:3]), id ~ strformat), on = .(id)]
# (same result as above)

myDT$other <- NULL
myDT[dcast(myDT[, unlist(lapply(.SD, strsplit, ":"), recursive = FALSE), by = id, .SDcols = 2:3], id ~ strformat), on = .(id)]
#      id   strformat       content    A    B    C   XX  whatever
#   1:  1         A:B         a1:b1   a1   b1 <NA> <NA>      <NA>
#   2:  2         A:C         a2:c2   a2 <NA>   c2 <NA>      <NA>
#   3:  3       B:A:C      b3:a3:c3   a3   b3   c3 <NA>      <NA>
#   4:  4         A:B         a4:b4   a4   b4 <NA> <NA>      <NA>
#   5:  5 XX:whatever xx5:whatever5 <NA> <NA> <NA>  xx5 whatever5

myDT[dcast(unnest(myDT[, lapply(.SD, tstrsplit, ":"),by = id, .SDcols = 2:3]), id ~ strformat), on = .(id)]
# (same correct result as above)

以下是删除“其他”列后的基准测试:

# make a bigger table based on a small one:
myDTbig <- myDT[sample(nrow(myDT),1e5, replace = T),]
myDTbig[, id:=seq_len(nrow(myDTbig))]
myDTbig$other <- NULL

require(microbenchmark)
print(microbenchmark(
  f_csplit(myDTbig), 
  f_lapply_str(myDTbig), 
  f_unnest(myDTbig), 
  f_cycle(myDTbig), 
  times=10L
), signif=2)

# Unit: milliseconds
#              expr      min   lq mean median   uq  max neval
# f_csplit(myDTbig)      420  430  470    440  450  670    10
# f_lapply_str(myDTbig) 4200 4300 4700   4700 5100 5400    10
# f_unnest(myDTbig)     3900 4400 4500   4500 4800 5100    10
# f_cycle(myDTbig)        88   96   98     98  100  100    10

并保留“其他”列:

# make a bigger table based on a small one:
myDTbig <- myDT[sample(nrow(myDT),1e5, replace = T),]
myDTbig[, id:=seq_len(nrow(myDTbig))]

require(microbenchmark)
print(microbenchmark(
  f_csplit(myDTbig), 
  f_cycle(myDTbig), 
  times=100L
), signif=2)

# Unit: milliseconds
#              expr min  lq mean median  uq  max neval
# f_csplit(myDTbig) 410 440  500    460 490 1300   100
# f_cycle(myDTbig)   84  93  110     96 100  270   100

下面是我的真实数据集。好吧,实际上,只有 1/10:在完整的情况下,我遇到了内存分配错误csplit解决方案(而带有循环的解决方案工作得很好)。

myDTbig <- dt.vcf[1:2e6,]
myDTbig[,id:=seq_len(nrow(myDTbig))]

print(microbenchmark(
  f_csplit(myDTbig, 'FORMAT', 'S_1'), 
  f_cycle(myDTbig, 'FORMAT', 'S_1'), 
  times=5L
), signif=2)
# Unit: seconds
#                              expr  min   lq mean median   uq  max neval
# f_csplit(myDTbig, "FORMAT", "S_1") 15.0 16.0   16   16.0 16.0 17.0     5
# f_cycle(myDTbig, "FORMAT", "S_1")   4.9  4.9    6    5.7  5.8  8.5     5

最后,我测试了是否有很多级别format列(即我们必须运行多少个周期)将增加循环求解的时间:

myDTbig <- myDT[sample(nrow(myDT),1e6, replace = T),]
myDTbig[, strformat:=paste0(strformat,sample(letters,1e6, replace = T)),]
length(unique(myDTbig$strformat)) # 104
myDTbig[, id:=seq_len(nrow(myDTbig))]

print(microbenchmark(
  f_csplit(myDTbig), 
  f_cycle(myDTbig), 
  times=10L
), signif=2)
# Unit: seconds
#             expr  min  lq mean median  uq max neval
# f_csplit(myDTbig) 7.3 7.4  7.7    7.6 7.9 8.4    10
#  f_cycle(myDTbig) 2.7 2.9  3.0    2.9 3.0 3.8    10

因此,作为结论 - 令人惊讶的是,对于这项任务,该循环的表现比其他任何循环都要好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

tstr在一轮中拆分到不同的列 的相关文章

  • 错误:“rjags”的包或命名空间加载失败

    在终端的 conda 环境之一中 我能够成功安装包 rjags 但是 当我在该环境中运行 R 并运行库 rjags 时 出现以下错误 加载所需的包 coda 错误 rjags 的包或命名空间加载失败 rjags 的 loadNamespac
  • 在 R 中绘制对数正态概率密度

    我正在尝试在 R 中生成对数正态概率密度图 其中包含 3 个不同的均值对数和标准差对数 我尝试了以下方法 但我的图表太丑了 看起来一点也不好看 x lt seq 0 10 length 100 a lt dlnorm x meanlog 0
  • R.matlab/readMat:readTag(this) 中出错

    我正在尝试使用 R matlab 将 matlab 文件读入 R 但遇到此错误 require R matlab r lt readMat file mat verbose T Trying to read MAT v5 file stre
  • 将 VLMC 拟合到很长的序列

    我正在尝试将 VLMC 拟合到最长序列为 296 个状态的数据集 我这样做如下所示 Load libraries library PST library RCurl library TraMineR Load and transform d
  • R 编程:如何计算数据框中两个单元格之间的差异并将它们保存在新列中

    尝试学习 R 并陷入自相关示例中 我想将 x 的差异与 y 的差异进行回归 我在数据框中有 x 和 y 并且希望将 x2 x1 的差值保存在新列 例如 dx 中 我不知道该怎么做 我拥有的 data1 x y 5 3 8 9 3 1 1 5
  • 将函数应用于 3d 数组的每一层,返回一个数组

    假设您有一个包含行 列和层的 3 维数组 A lt array 1 27 c 3 3 3 想象你有一个函数 它接受一个矩阵作为输入并返回一个矩阵作为输出 就像t 如何将该函数应用于数组的每一层 返回与第一层大小相同的另一个数组 我觉得我应该
  • 比较 R 中的两个字符向量

    我有两个 ID 字符向量 我想比较这两个字符向量 特别是我对以下数字感兴趣 A和B各有多少个ID 有多少个ID在A中但不在B中 有多少个ID在B但不在A 我还想画维恩图 以下是一些可以尝试的基础知识 gt A c Dog Cat Mouse
  • 为绘图制作 2D 图例 - 双变量分区统计图

    我一直在玩双变量 choropleth 地图 并且一直在如何创建类似于 2d 图例的问题上陷入困境约书亚 史蒂文斯 http www joshuastevens net cartography make a bivariate chorop
  • 如何将此“for”循环转换为向量解

    这个问题与 将嵌入其他文本的长州名称转换为两个字母的州缩写 https stackoverflow com questions 25582518 convert long state names embedded with other te
  • glmnet 未从 cv.glmnet 收敛 lambda.min

    我跑了20倍cv glmnet套索模型以获得 lambda 的 最佳 值 但是 当我尝试重现结果时glmnet 我收到一个错误 内容如下 Warning messages 1 from glmnet Fortran code error c
  • R 中的字符串作为函数参数

    数据框chocolates列出了糖果的类型以及每种糖果的一组评级 ID sweetness filling crash snickers 0 67 0 55 0 40 milky way 0 81 0 53 0 56 我正在编写一个函数 它
  • ggplot散点图中的图例问题

    我想使用 ggplot 创建显示方法比较数据的散点图 绘图应包含原始数据 理想线和带误差的拟合线 图例应显示理想线和拟合线的线型 线宽 线颜色 我可以获得大部分我想要的东西 但是图例存在以下问题 图例显示每种线型有 2 条线 为什么 如何解
  • 如何将 ggrough 图表另存为 .png

    说我正在使用R包裹ggrough https xvrdm github io ggrough https xvrdm github io ggrough 我有这个代码 取自该网页 library ggplot2 library ggroug
  • 从数据框创建稀疏矩阵

    我正在做一项作业 尝试为 Netflix 奖项数据构建协作过滤模型 我使用的数据位于 CSV 文件中 我可以轻松地将其导入到数据框中 现在我需要做的是创建一个稀疏矩阵 其中用户作为行 电影作为列 每个单元格都由相应的评级值填充 当我尝试绘制
  • 如何修改秤包生成的标签?

    所以我正在制作金字塔可视化 我在用着scale y continuous labels scales label number si accuracy 0 1 来生产标签 但是 我想去掉图表女性部分的负号 我认为保留 SI 后缀但删除负号的
  • 检查单词是否存在于英语词典 r 中

    我正在对多个进行一些文本分析resume生成一个wordcloud using wordcloud包装连同tm用于在 R 中预处理文档语料库的包 我面临的问题是 检查语料库中的单词是否具有某种含义 即 它属于英语词典 如何一起挖掘 处理多份
  • 根据R中的前一行和当前行按组计算

    我可以根据 R 中的前一行和当前行进行计算 对于此数据框 df A B 1 2 2 2 2 3 3 4 5 5 B2 A2 0 5 B1 我可以使用这段代码来计算这个函数 for i in 2 nrow df B i lt 1 2 B i
  • 使用 R 交互式更改 Plotly 图像中的轴刻度(线性/对数)

    Goal 创建交互式下拉菜单 按钮来更新 R 中 Plotly 图形的轴比例 Issue 有很多关于创建的文档buttons https plot ly r custom buttons and 对数图 https plot ly r lo
  • 如何一次导入多个 .csv 文件?

    假设我们有一个包含多个 data csv 文件的文件夹 每个文件包含相同数量的变量 但每个文件来自不同的时间 R 中有没有办法同时导入它们 而不必单独导入它们 我的问题是 我有大约 2000 个数据文件需要导入 并且必须使用以下代码单独导入
  • 使用 purrr、broom 从许多单变量模型中获得整洁的输出

    我有一个由二进制结果列组成的数据框 y 和多个独立的预测列 x1 x2 x3 我想运行许多单变量逻辑回归模型 例如y x1 y x2 y x3 并将每个模型的指数系数 比值比 95 置信区间和 p 值提取到数据框 标题的行中 在我看来 使用

随机推荐