r - tidyr 宽到长 : repeated measures and efficiency

标签 r data.table tidyr

这个问题与this question有关,并由 Akrun 回答。

我有包含嵌套列的宽数据,我正在将这些数据转换为长格式。数据采用以下部分长格式:

  id   var value
  1 diag1     m
  1 diag2     h
  1 diag3     k
  1 diag4     r
  1 diag5     c
  1 diag6     f
  1 opa1      s
  1 opa2      f

我想以以下真正的长格式获取它们:
  id diag number value
  1 diag      1     m
  1 diag      2     h
  1 diag      3     k
  1 diag      4     r
  1 diag      5     c
  1 diag      6     f
  1 opa       1     s
  1 opa       2     f

以下代码针对较少的行数实现了这一点,但我的数据有点复杂(15 位 id ,5 位 value ),并且我有 6.34 亿行。

对于我的数据,100 行大约需要 3 秒,并且在超过 1,000 行时崩溃。

这是一些带有计时的示例,可重现的代码
library(tidyr)
set.seed(10)
n = 100
diags <- paste("diag", 1:25, sep="")
poas <-paste("poa", 1:25, sep="")
var <- c(diags, poas)

dat <- data.frame(id = rep(1:50, each=n), var = rep(var, 5), value = letters[sample(1:25,25*n, replace = T)])

datlong <- dat %>%
  extract(var, c('diag', 'number'), 
          '([a-z]+)([0-9]+)')

n      user    system  elapsed 
10^2   0.011   0.006   0.026
10^3   0.041   0.010   0.066
10^4   0.366   0.055   0.421
10^5   3.969   0.445   4.984 
10^6   40.777  13.840  60.969 

我的数据框如下所示:
str(realdata)
'data.frame':   634358112 obs. of  3 variables:
 $ visitId: Factor w/ 12457767 levels "---------_1981-07-28",..: 8333565 5970358 158415 5610904 3422522 10322908 10973353 10921570 919501 4639482 ...
 $ var    : Factor w/ 48 levels "odiag1","odiag2",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ value  : chr  "42732" "0389" "20280" "9971" ...

我也尝试将 value 字段转换为一个因子,结果相似。

有没有更有效的方法来完成这项工作?

更新:
结果与 separate正如@Richard 所建议的
n      user    system  elapsed 
10^2   0.010   0.001   0.010 
10^3   0.081   0.003   0.084
10^4   0.797   0.011   0.811 
10^5   9.703   0.854  11.041 
10^6   138.401 6.301 146.613

结果与 data.table正如阿克伦所建议的
n      user    system  elapsed 
10^2   0.018   0.001   0.019  
10^3   0.074   0.002   0.076
10^4   0.598   0.024   0.619 
10^5   6.478   0.348   6.781 
10^6   73.581   2.661  75.749

结果与 fread正如阿克伦所建议的
n      user    system  elapsed 
10^2   0.019   0.001   0.019  
10^3   0.065   0.003   0.067 
10^4   0.547   0.011   0.547 
10^5   5.321   0.164   5.446  
10^6   52.362   1.363  53.312 

最佳答案

我们可以试试 tstrsplit来自 data.table

library(data.table)#v1.9.6+
setDT(df1)[, c('diag', 'number') := tstrsplit(var,
             '(?<=[^0-9])(?=[0-9])', perl=TRUE)]

或者在字符和数字元素之间创建一个分隔符,然后用 fread 读取
fread(paste(sub('(\\d+)$', ',\\1', df1$var), collapse='\n'), 
                 col.names=c('diag', 'number'))

关于r - tidyr 宽到长 : repeated measures and efficiency,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34230184/

相关文章:

r - 每年使用 dplyr 或数据表的公司数量

r - 根据由冒号和连接向量定义的序列字符串创建长数据格式

r - 使用 sf 和 ggplot2 在 +/- 180 日期变更线周围绘图

r - 是否可以自动化 R markdown 文件?

R data.table 大小和内存限制

r - r中data.table中的部分滚动总和

r - 建模师 : Fitting multiple models with resampled data

r - 在 R 中划分行

r - 使用 ggplot 记录计数的时间序列

r - 在 R 中叠加 10 个密度图,颜色与重叠图的数量成正比