【问题标题】:split a dataframe column by regular expression on characters separated by a "."通过正则表达式拆分由“。”分隔的字符的数据框列
【发布时间】:2013-08-30 04:45:57
【问题描述】:

在 R 中,我有以下数据框:

     Name     Category
1    Beans    1.12.5
2    Pears    5.7.9
3    Eggs     10.6.5

我想要的是:

     Name     Cat1    Cat2    Cat3
1    Beans    1       12      5
2    Pears    5       7       9
3    Eggs     10      6       5

理想情况下,plyr 中内置的一些表达式会很好......

我会站在我这边进行调查,但由于搜索这可能需要我很多时间,我只是想知道你们中的一些人是否有一些执行此操作的提示...

【问题讨论】:

  • 您是否希望每个项目都恰好有三个类别?
  • 你说得对,我应该更精确一点,有些答案的类别少于或多于 3 个,最少 1 个,最多 5 个!

标签: regex r plyr


【解决方案1】:

我已经编写了一个函数concat.split(实际上是一个“函数系列”)作为我的splitstackshape 包的一部分来处理这些类型的问题:

# install.packages("splitstackshape")
library(splitstackshape)
concat.split(mydf, "Category", ".", drop=TRUE)
#    Name Category_1 Category_2 Category_3
# 1 Beans          1         12          5
# 2 Pears          5          7          9
# 3  Eggs         10          6          5

它也适用于“不平衡”数据。

dat <- data.frame(Name = c("Beans", "Pears", "Eggs"), 
                  Category = c("1.12.5", "5.7.9.8", "10.6.5.7.7"))
concat.split(dat, "Category", ".", drop = TRUE)
#    Name Category_1 Category_2 Category_3 Category_4 Category_5
# 1 Beans          1         12          5         NA         NA
# 2 Pears          5          7          9          8         NA
# 3  Eggs         10          6          5          7          7

因为在这些类型的情况下通常需要“长”或“熔”数据,所以concat.split.multiple 函数也有一个“长”参数:

concat.split.multiple(dat, "Category", ".", direction = "long")
#     Name time Category
# 1  Beans    1        1
# 2  Pears    1        5
# 3   Eggs    1       10
# 4  Beans    2       12
# 5  Pears    2        7
# 6   Eggs    2        6
# 7  Beans    3        5
# 8  Pears    3        9
# 9   Eggs    3        5
# 10 Beans    4       NA
# 11 Pears    4        8
# 12  Eggs    4        7
# 13 Beans    5       NA
# 14 Pears    5       NA
# 15  Eggs    5        7

【讨论】:

  • 我看到它处理了值不相等的情况。
  • 我新的 splitstackshape-concat.split.multiple-life 的第一天!未来是光明的! +1
  • @Henrik,错误报告/功能增强here 请 :)
【解决方案2】:

qdap 包有 colsplit2df 用于这些情况:

#recreate your data first:
dat <- data.frame(Name = c("Beans", "Pears", "Eggs"), Category = c("1.12.5", 
"5.7.9", "10.6.5"),stringsAsFactors=FALSE)

library(qdap)
colsplit2df(dat, 2, paste0("cat", 1:3))

## > colsplit2df(dat, 2, paste0("cat", 1:3))
##    Name cat1 cat2 cat3
## 1 Beans    1   12    5
## 2 Pears    5    7    9
## 3  Eggs   10    6    5

【讨论】:

    【解决方案3】:

    如果您的类别数量一致,那么这将起作用:

    #recreate your data first:
    dat <- data.frame(Name = c("Beans", "Pears", "Eggs"), Category = c("1.12.5", 
    "5.7.9", "10.6.5"),stringsAsFactors=FALSE)
    
    spl <- strsplit(dat$Category,"\\.")
    len <- sapply(spl,length)
    dat[paste0("cat",1:max(len))] <- t(sapply(spl,as.numeric))
    

    结果:

    dat
       Name Category cat1 cat2 cat3
    1 Beans   1.12.5    1   12    5
    2 Pears    5.7.9    5    7    9
    3  Eggs   10.6.5   10    6    5
    

    如果您有不同数量的分隔值,那么这应该是原因:

    #example unbalanced data
    dat <- data.frame(Name = c("Beans", "Pears", "Eggs"), Category = c("1.12.5", 
    "5.7.9", "10.6.5"),stringsAsFactors=FALSE)
    dat$Category[2] <- "5.7"
    
    spl <- strsplit(dat$Category,"\\.")
    len <- sapply(spl,length)
    spl <- Map(function(x,y) c(x,rep(NA,max(len)-y)), spl, len)
    
    dat[paste0("cat",1:max(len))] <- t(sapply(spl,as.numeric))
    

    结果:

       Name Category cat1 cat2 cat3
    1 Beans   1.12.5    1   12    5
    2 Pears      5.7    5    7   NA
    3  Eggs   10.6.5   10    6    5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-23
      • 1970-01-01
      • 2019-04-05
      相关资源
      最近更新 更多