【问题标题】:Splitting a string into new rows in R [duplicate]将字符串拆分为R中的新行[重复]
【发布时间】:2014-10-13 14:54:43
【问题描述】:

我有一个如下数据集:

Country Region    Molecule      Item Code   
    IND     NA       PB102      FR206985511 
   THAI     AP       PB103      BA-107603 / F000113361 / 107603
   LUXE     NA       PB105      1012701 / SGP-1012701 / F041701000
    IND     AP       PB106      AU206985211 / CA-F206985211
   THAI     HP       PB107      F034702000 / 1010701 / SGP-1010701
   BANG     NA       PB108      F000007970/25781/20009021

我想根据/ITEMCODE 列中的字符串值进行拆分,并为每个条目创建一个新行。

例如,所需的输出将是:

Country Region Molecule      Item.Code
    IND     NA    PB102    FR206985511
   THAI     AP    PB103      BA-107603
   THAI     AP    PB103     F000113361
   THAI     AP    PB103         107603
   LUXE     NA    PB105        1012701
   LUXE     NA    PB105    SGP-1012701
   LUXE     NA    PB105     F041701000
    IND     AP    PB106    AU206985211
    IND     AP    PB106  CA-F206985211
   THAI     HP    PB107     F034702000
   THAI     HP    PB107        1010701
   THAI     HP    PB107    SGP-1010701
   BANG     NA    PB108     F000007970
   BANG     NA    PB108          25781
   BANG     NA    PB108       20009021

我试过下面的代码

library(splitstackshape)
df2=concat.split.multiple(df1,"Plant.Item.Code","/", direction="long")

但出现错误

"Error: memory exhausted (limit reached?)"

当我尝试strsplit() 时,我收到以下错误消息。

Error in strsplit(df1$Plant.Item.Code, "/") : non-character argument

【问题讨论】:

  • 对于第二个错误,您可以使用strsplit(as.character(df1$Plant.Item.Code, "/") 假设列是factor
  • 我在下面赞同大卫的回答。它会更有效率。您正在使用的当前函数依赖于 reshape 函数,该函数速度较慢并且可能会遇到内存问题。

标签: r split dataframe strsplit


【解决方案1】:

试试cSplit 函数(因为你已经在使用@Anandas 包了)。请注意,这将返回一个 data.table 对象,因此请确保您已安装此包。您可以通过执行setDF(df2) 之类的操作恢复到data.frame(如果您愿意)

library(splitstackshape)
df2 <- cSplit(df1, "Item.Code", sep = "/", direction = "long")
df2
#     Country Region Molecule      Item.Code
#  1:     IND     NA    PB102    FR206985511
#  2:    THAI     AP    PB103      BA-107603 
#  3:    THAI     AP    PB103     F000113361 
#  4:    THAI     AP    PB103         107603
#  5:    LUXE     NA    PB105        1012701 
#  6:    LUXE     NA    PB105    SGP-1012701 
#  7:    LUXE     NA    PB105     F041701000
#  8:     IND     AP    PB106    AU206985211 
#  9:     IND     AP    PB106  CA-F206985211
# 10:    THAI     HP    PB107     F034702000 
# 11:    THAI     HP    PB107        1010701 
# 12:    THAI     HP    PB107    SGP-1010701
# 13:    BANG     NA    PB108     F000007970
# 14:    BANG     NA    PB108          25781
# 15:    BANG     NA    PB108       20009021

【讨论】:

  • 非常感谢 David.. 这确实有效并且是超快速的解决方案。
  • 有没有办法为这个功能添加进度条?
  • @510947,你好像已经在github上提交了请求没有?
  • 嗯,是的...只是针对更多的受众 :)
【解决方案2】:

基础 R 中的另一种方法:

as.data.frame(do.call(rbind, apply(df1, 1, function(x) {
      do.call(expand.grid, strsplit(x, " */ *"))
})))

结果:

   Country Region Molecule     Item.Code
1      IND   <NA>    PB102   FR206985511
2     THAI     AP    PB103     BA-107603
3     THAI     AP    PB103    F000113361
4     THAI     AP    PB103        107603
5     LUXE   <NA>    PB105       1012701
6     LUXE   <NA>    PB105   SGP-1012701
7     LUXE   <NA>    PB105    F041701000
8      IND     AP    PB106   AU206985211
9      IND     AP    PB106 CA-F206985211
10    THAI     HP    PB107    F034702000
11    THAI     HP    PB107       1010701
12    THAI     HP    PB107   SGP-1010701
13    BANG   <NA>    PB108    F000007970
14    BANG   <NA>    PB108         25781
15    BANG   <NA>    PB108      20009021

【讨论】:

    【解决方案3】:

    试试这样的

    d <- structure(list(Country = c("A", "B", "C"), `Item Code` = c("FR206985511", 
        "BA-107603/F000113361/107603", "1012701/SGP-1012701/F041701000")),
        .Names = c("Country", "Item Code"), row.names = c(NA, -3L),
        class = "data.frame")
    d
    #   Country                      Item code
    #         A                    FR206985511
    #         B    BA-107603/F000113361/107603
    #         C 1012701/SGP-1012701/F041701000
    
    codes <- strsplit(d$"Item Code", "/")
    code.lengths <- sapply(codes, length)
    new.d <- d[rep(1:nrow(d), code.lengths), ]
    new.d$"Item Code" <- unlist(codes)
    new.d 
    #    Country   Item Code
    #1         A FR206985511
    #2         B   BA-107603
    #2.1       B  F000113361
    #2.2       B      107603
    #3         C     1012701
    #3.1       C SGP-1012701
    #3.2       C  F041701000
    

    如果你想去掉空格(你的原始数据似乎包含),你可以通过d$"Item Code" &lt;- gsub(" ", "", d$"Item Code")来实现

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-01
      • 1970-01-01
      • 2021-12-28
      • 2014-06-24
      • 1970-01-01
      • 2020-08-24
      • 2016-03-13
      • 2013-02-12
      相关资源
      最近更新 更多