【问题标题】:R semicolon delimited a column into rowsR分号将一列分隔为行
【发布时间】:2015-04-27 10:49:17
【问题描述】:

我正在使用 RStudio 2.15.0,并使用 XLConnect 从 Excel 创建了一个对象,其中包含 3000 多行和 12 列我正在尝试将一列分隔/拆分为行,但不知道这是否可行或如何做。下面的数据示例使用连接的 3 列。对此的任何帮助都将是巨大的。

适用于其中 2 列的代码如下。

v1 <- with(df, tapply(PolId, Description,  FUN= function(x) {
x1 <- paste(x, collapse=";")
gsub('(\\b\\S+\\b)(?=.*\\b\\1\\b.*);', '',     x1, perl=TRUE)}))
library(stringr)
Description <- rep(names(v1),  str_count(v1, '\\w+'))
PolId <- scan(text=gsub(';+', ' ', v1), what='', quiet=TRUE)
data.frame(PolId, Description)  

样本数据

PolId   Description  Document.Type
ABC123;ABC456;ABC789;   TEST1  Pol1
ABC123;ABC456;ABC789;   TEST1  Pol1
ABC123;ABC456;ABC789;   TEST1  Pol1
AAA123; TEST1  End1
AAA123; TEST2  End2
ABB123;ABC123;  TEST3  End1
ABB123;ABC123;  TEST3  End1

我希望输出是这样的(替换重复的 Polid)

PolId   Description  Document.Type
ABC123  TEST1        Pol1
ABC456  TEST1        Pol1
ABC789  TEST1        Pol1
AAA123  TEST1        End1
AAA123  TEST2        End2
ABB123  TEST3        End1
ABC123  TEST3        End1

【问题讨论】:

  • 你看我的第二个解决方案了吗?它为您提供准确的输出,而无需修改它...
  • David 我在使用 cSplit 时收到以下错误。库(splitstackshape)唯一(cSplit(df,“PolId”,“;”,“long”))唯一错误(cSplit(df,“PolId”,“;”,“long”)):找不到函数“ cSplit"
  • 重新安装包。你可能有一个旧版本

标签: r split delimiter


【解决方案1】:

这是一个基本的 R 解决方案。使用strplit 拆分PolId 字段,并为每个这样的拆分字段将其与相应的Description 绑定。这给出了我们一起rbind 的矩阵列表。最后设置列名。

out <- do.call(rbind, Map(cbind, strsplit(DF$PolId, ";"), DF$Description))
colnames(out) <- colnames(DF)

给予:

> out
      PolId    Description
 [1,] "ABC123" "TEST1"    
 [2,] "ABC456" "TEST1"    
 [3,] "ABC789" "TEST1"    
 [4,] "ABC123" "TEST1"    
 [5,] "ABC456" "TEST1"    
 [6,] "ABC789" "TEST1"    
 [7,] "ABC123" "TEST1"    
 [8,] "ABC456" "TEST1"    
 [9,] "ABC789" "TEST1"    
[10,] "AAA123" "TEST1"    
[11,] "AAA123" "TEST2"    
[12,] "ABB123" "TEST3"    
[13,] "ABC123" "TEST3"    
[14,] "ABB123" "TEST3"    
[15,] "ABC123" "TEST3" 

注意:我们使用这个作为输入:

DF <-
structure(list(PolId = c("ABC123;ABC456;ABC789;", "ABC123;ABC456;ABC789;", 
"ABC123;ABC456;ABC789;", "AAA123;", "AAA123;", "ABB123;ABC123;", 
"ABB123;ABC123;"), Description = c("TEST1", "TEST1", "TEST1", 
"TEST1", "TEST2", "TEST3", "TEST3")), .Names = c("PolId", "Description"
), class = "data.frame", row.names = c(NA, -7L))

【讨论】:

  • 谢谢你,虽然我得到了以下信息。 > out colnames(out) colnames<-(*tmp* 中的错误, value = c("Document.Title", "Document.Type", : 'dimnames' [2] 的长度不等于数组范围
  • 用答案中使用的输入试试。如果这对您有用并且不适用于您的实际输入,那么确定您的实际输入与使用的输入有何不同。通常,将dput(DF) 的输出放在您的问题中以使其明确。
【解决方案2】:

这是一个快速的data.table 可能的解决方案

library(data.table)
unique(setDT(df)[, .(PolId = unlist(strsplit(as.character(PolId), ";"))), by = Description])
#    Description  PolId
# 1:       TEST1 ABC123
# 2:       TEST1 ABC456
# 3:       TEST1 ABC789
# 4:       TEST1 AAA123
# 5:       TEST2 AAA123
# 6:       TEST3 ABB123
# 7:       TEST3 ABC123

根据您的编辑 - 另一个选项(如果您有两个以上的列)

library(splitstackshape)
unique(cSplit(df, "PolId", ";", "long"))
#     PolId Description Document.Type
# 1: ABC123       TEST1          Pol1
# 2: ABC456       TEST1          Pol1
# 3: ABC789       TEST1          Pol1
# 4: AAA123       TEST1          End1
# 5: AAA123       TEST2          End2
# 6: ABB123       TEST3          End1
# 7: ABC123       TEST3          End1

【讨论】:

    【解决方案3】:

    您可以在拆分“PolId”列并获取unique 行后,从tidyr 尝试unnest

    library(dplyr)
    library(tidyr)
     unnest(setNames(strsplit(df$PolId, ';'), df$Description), 
                                      Description) %>% unique()
    

    或者使用base Rstack/strsplit/duplicated。用分隔符(;)分割“PolId”(strsplit),用“Description”列命名输出列表元素,stack列表得到一个“data.frame”并使用duplicated删除重复的行。

    df1 <- stack(setNames(strsplit(df$PolId, ';'), df$Description))
    setNames(df1[!duplicated(df1),], names(df))
    #     PolId Description
    #1  ABC123       TEST1
    #2  ABC456       TEST1
    #3  ABC789       TEST1
    #10 AAA123       TEST1
    #11 AAA123       TEST2
    #12 ABB123       TEST3
    #13 ABC123       TEST3
    

    或者不使用strsplit的其他选项

    v1 <- with(df, tapply(PolId, Description, FUN= function(x) {
                x1 <- paste(x, collapse=";")
            gsub('(\\b\\S+\\b)(?=.*\\b\\1\\b.*);', '', x1, perl=TRUE)}))
    library(stringr)
    Description <- rep(names(v1),  str_count(v1, '\\w+'))
    PolId <- scan(text=gsub(';+', ' ', v1), what='', quiet=TRUE)
    data.frame(PolId, Description)
    #   PolId Description
    #1 ABC123       TEST1
    #2 ABC456       TEST1
    #3 ABC789       TEST1
    #4 AAA123       TEST1
    #5 AAA123       TEST2
    #6 ABB123       TEST3
    #7 ABC123       TEST3
    

    【讨论】:

    • 道歉,但我不明白 gsub 代码,但这有效。如果我想在代码中添加一个额外的列,我该怎么做?
    • 您能否使用附加列更新问题,因为它会很清楚。 gsub 只保留唯一值并丢弃重复项
    • 或这个变体:df %&gt;% mutate(PolId = strsplit(PolId, ";")) %&gt;% unnest()
    猜你喜欢
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 2021-12-10
    相关资源
    最近更新 更多