【问题标题】:dataframe in R: lookup multiple strings in a cell that are separated by a commaR中的数据框:在一个以逗号分隔的单元格中查找多个字符串
【发布时间】:2017-09-07 13:46:20
【问题描述】:

假设列 (letter_strings) 中的每一行都有由逗号分隔的可变数量的字符串。例如:

letter_strings

abc, def, ghi, jkl 
mno, pqr
stu, vw, xyz

我想查找数据框中的每个字符串:

letter_strings code

abc YES
def NO
ghi MAYBE
jkl SURE
mno PERHAPS
pqr ALWAYS
stu NEVER
vw NOGO
xyz ABSENT

并在附加列中获取以下相应行

YES, NO, MAYBE, SURE
PERHAPS, ALWAYS
NEVER, NOGO, ABSENT

这在R中可能吗,我真的不知道如何解决这个问题......

提前致谢!

W

【问题讨论】:

  • 请在您的问题正文中提供您的数据dput。确定您正在使用的数据的实际结构将很有帮助。如果它很大,那么dput(head(dat, 10)) 左右就足够了。

标签: r string dataframe lookup strsplit


【解决方案1】:

1) gusbfn

gsubfn 类似于gsub,只是它在查找列表lookup 的名称中查找与正则表达式(此处定义为"\\w+",即单词字符序列)的匹配项,替换目标字符串中的名称及其在lookup 中的值。

library(gsubfn)

lookup <- with(DF2, as.list(setNames(code, letter_strings)))
transform(DF1, codes = gsubfn("\\w+", lookup, letter_strings))

给予:

      letter_strings                codes
1 abc, def, ghi, jkl YES, NO, MAYBE, SURE
2           mno, pqr      PERHAPS, ALWAYS
3       stu, vw, xyz  NEVER, NOGO, ABSENT

2) dplyr/tidyr 将 DF1 转换为长格式,将其与 DF2 连接,然后将其重新整形为原始格式:

library(dplyr)
library(tidyr)

DF1 %>% 
    mutate(id = 1:n()) %>% 
    separate_rows(letter_strings) %>% 
    left_join(DF2) %>% 
    group_by(id) %>% 
    summarise(letter_string = toString(letter_strings), codes = toString(code)) %>% 
    ungroup %>%
    select(-id)

给予:

Joining, by = "letter_strings"
# A tibble: 3 x 2
       letter_string                codes
               <chr>                <chr>
1 abc, def, ghi, jkl YES, NO, MAYBE, SURE
2           mno, pqr      PERHAPS, ALWAYS
3       stu, vw, xyz  NEVER, NOGO, ABSENT

3) strsplit/merge/aggregate 使用strsplitDF1stack 中的字符串拆分为长格式st。然后mergeDF2aggregate 回到原来的形式。没有使用任何包。

s <- strsplit(DF1$letter_strings, ", ")
st <- stack(setNames(s, seq_along(s)))
m <- merge(st, DF2, by = 1, all.x = TRUE, all.y = FALSE)
aggregate(. ~ ind, m, toString)[-1]

给予:

              values                 code
1 abc, def, ghi, jkl YES, NO, MAYBE, SURE
2           mno, pqr      PERHAPS, ALWAYS
3       stu, vw, xyz  NEVER, NOGO, ABSENT

3a) magrittr 这可以用 magrittr 来表达:

library(magrittr)

DF1 %>%
    "$"("letter_strings") %>%
    strsplit(", ") %>%
    setNames(seq_along(.)) %>%
    stack %>%
    merge(DF2, by = 1, all.x = TRUE, all.y = FALSE) %>%
    aggregate(. ~ ind, ., toString) %>%
    "["(-1)


s <- stack(setNames(strsplit(DF1$letter_strings, ", "), 1:nrow(DF1)))
m <- merge(s, DF2, by = 1, all.x = TRUE, all.y = FALSE)
aggregate(. ~ ind, m, toString)[-1]

4) data.table 请注意,在下面的评论中,@Uwe 提供了 (2) 和 (3) 中的方法的 data.table 版本,用于转换为长格式,加入并转换回来。

注意:可重复形式的输入:

Lines1 <- "
letter_strings
abc, def, ghi, jkl
mno, pqr
stu, vw, xyz"
DF1 <- read.table(text = Lines1, header = TRUE, as.is = TRUE, sep = ";")

Lines2 <- "
letter_strings code
abc YES
def NO
ghi MAYBE
jkl SURE
mno PERHAPS
pqr ALWAYS
stu NEVER
vw NOGO
xyz ABSENT"
DF2 <- read.table(text = Lines2, header = TRUE, as.is = TRUE)

【讨论】:

  • 谢谢!您的解决方案非常适合我的需要!
  • 如果你想添加一个data.table 版本的reshape to long, join, reshape back to widelibrary(data.table); setDT(DF1); setDT(DF2); DF2[DF1[, rn := .I][, strsplit(letter_strings, ", ", fixed = TRUE), by = rn], on = .(letter_strings = V1)][, lapply(.SD, toString), by = rn][, -"rn"]
【解决方案2】:

如果没有太多的字母字符串,您可以在循环中使用gsub 执行此操作。

Temp = letter_strings
for(i in 1:nrow(df)) {
    Temp = gsub(df$letter_strings[i], df$code[i], Temp) }
Temp
[1] "YES, NO, MAYBE, SURE" "PERHAPS, ALWAYS"      "NEVER, NOGO, ABSENT" 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多