【问题标题】:Split arbitrary column into melted data frame将任意列拆分为融化的数据框
【发布时间】:2015-08-18 10:11:34
【问题描述】:

我有一个带有结构化数据的丑陋列的 data.frame。每列可以保存 1 到 40 个感兴趣的值。每个值都用 html 分隔符 "<br />" 分隔。以1.1的形式提取的值,即一个整数一个句点和另一个整数。

如何将这些列分离并融合成不同的行?

我知道 lapply 和 tidy::separate 可能是要走的路。但我还没有成功。所以寻求帮助。

测试数据在这里:

testdata <- dget("http://pastebin.com/download.php?i=VS2cq2rB")

数据框包含两个列:"id""moduler"

我想改用“id”和“value”。最终结果应该是这样的。

"id", "value"
1, 1.1
1, 1.2
1, 1.3
1, 2.4
2, 1.1
2, 1.3
2, 3.3

这是我最近的一次尝试——与我开始使用 lapply 的地方相去甚远。

origdf <- data.frame()
#names(newdf) <- c("id", 'pnummer', 'moduler')

for (i in 1:nrow(hs)) {
  newdf <- data.frame()
  newdf[i, 'id'] <- hs[i, 'id']
  newdf[i, 'pnummer'] <- hs[i, 'pnummer']
  tmp <- unlist(strsplit(as.character(hs[i,'moduler']), "<br />", fixed=T))
  for (m in 3:length(tmp)+3) {
    newdf[i, m] <- tmp[m]
  }
  origdf <- dplyr::bind_rows(newdf, origdf)
}

【问题讨论】:

  • @SabDeM 你看到了什么? sabdemtest pastebin.com/download.php?i=VS2cq2rB") - 适用于 mee(尽管数据看起来很有趣 - 这就是我要解决的问题:-))

标签: r lapply tidyr


【解决方案1】:

这是一种可能的data.table 方法。基本上我只是将moduler 拆分为"&lt;br /&gt;""&lt;br /&gt;Installationsmontør" 拆分为id

library(data.table)
setDT(testdata)[, .(value = unlist(strsplit(as.character(moduler), 
                            "<br />|<br />Installationsmontør"))), by = id]
#        id value
#   1: 2862   1.1
#   2: 2862   1.2
#   3: 2862   1.3
#   4: 2862   1.4
#   5: 2862   1.5
# ---           
# 132: 2877   3.6
# 133: 2877   4.1
# 134: 2877   4.4
# 135: 2877   4.5
# 136: 2877   4.6

或与splitstackshape 包类似

library(splitstackshape)
cSplit(testdata, splitCols = "moduler", 
       sep = "<br />|<br />Installationsmontør", 
       direction = "long", fixed = FALSE, stripWhite = FALSE)

【讨论】:

    【解决方案2】:

    我会尝试使用带有简单循环的 strsplit 函数:

    newdata  <-  NULL
    a <- 1
    b <- 0
    for (k in 1:length(testdata$moduler)) {
      M <- unlist(strsplit(as.character(testdata$moduler[k]),"<br />|<br />Installationsmontør"))
      b <- b + length(M)
      newdata$moduler[a:b] <- M
      newdata$id[a:b] <- testdata$id[k]
      a <- b + 1
    }
    newdata <- as.data.frame(newdata)
    

    【讨论】:

    • 谢谢 - 它工作。标记戴维斯回答为已接受,因为我认为这种方法更可靠。但我也在这里学到了一些东西。对我来说很棒:-)
    【解决方案3】:

    这是另一个使用来自tidyrunnest 的选项。我们使用来自library(stringr)str_extract_all 提取数字部分([0-9.]+)。输出为list。我们将list元素的名称设置为'testdata'和unnest的'id'列

     library(tidyr)
     library(stringr) 
     res <- unnest(setNames(lapply(str_extract_all(testdata$moduler, '[0-9.]+'), 
                       as.numeric), testdata$id), id)
     colnames(res)[2] <- 'value'
     head(res)
     #   id  value
     #1 2862 1.1
     #2 2862 1.2
     #3 2862 1.3
     #4 2862 1.4
     #5 2862 1.5
     #6 2862 1.6
    
     dim(res)
     #[1] 136   2
    

    或者base R 方法是在list 中提取带有regmatches/gregexpr 的数字元素,使用lengths 获取list 元素的length,从'复制'id' 列testdata' 基于此,unlist 'lst' 并创建一个新的 'data.frame'。

     lst <- lapply(regmatches(testdata$moduler, gregexpr('[0-9.]+',
                  testdata$moduler)), as.numeric)
     res2 <- data.frame(id = testdata$id[rep(1:nrow(testdata), lengths(lst))],
                                value= unlist(lst))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-15
      • 1970-01-01
      • 2014-08-25
      • 1970-01-01
      • 1970-01-01
      • 2022-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多