【问题标题】:data manipulation - splitting and shaping one data frame by matching values to another data frame数据操作 - 通过将值匹配到另一个数据帧来拆分和整形一个数据帧
【发布时间】:2016-09-08 17:33:46
【问题描述】:

下面给出了两个数据框:

df1

ob         optcode
1 flora   gg,bb,cc, pb
2 alexa    tt,dd, pb
3 dixon      gg, cc

df2

obname   type
1     gg orange
2     bb  apple
3     cc  nooption     
4     tt  grape
5     pb  nooption     
6     dd  melon

我正在做的是使用 cSplit 或 strsplit 函数之类的方法拆分 df1 中的“optcode”列,但这些值应该进入它们对应的列,如 df2 中所述。因此对于 df1 中的 row-1,flora 在 gg,bb,cc 的 optcode 下具有三个值。应该拆分这些值,以便 gg 与 df2 中的类型匹配,然后列名成为类型,而 'gg' 作为值。其余的也一样。结果应该是:

df3

 ob        nooption    orange apple grape  melon
1 flora      cc, pb     gg     bb    none   none
2 alexa      pb        none   none    tt     dd
3 dixon      cc        gg   none   none   none 

要注意的另一件事是,如果 df2 中的 optcode 没有类型,那么对于其余类型,应该有一个空字符串或 NA 或不显示。如果没有与该值关联的类型,则应该有与类型一样多的列加上一个附加的选项列,其中填充一个值。希望解释是有道理的。

我已经在 df1 上尝试了 cSplit,它运行成功,但由于之后需要更多手动处理,因此没有达到预期的结果。

期待听到实现上述目标的建议和方法。

谢谢。

【问题讨论】:

  • 为什么不分享您已经编写的代码,以便我们帮助完成最后一步,而不是让我们从头开始。

标签: r string split


【解决方案1】:

我们可以使用data.table 和splitstackshape 来做到这一点。使用splitstackshape 中的cSplit,我们通过分隔符, 将'optcode' 拆分为long 格式,然后将join on 'optcode' 与来自第二个数据集('df2 '),使用来自 'optcode' 的值创建一个 'options' 列,其中 'type' 为空白("" - 我们将其指定为 i)。使用dcast,将“长”格式转换为“宽”格式。

library(data.table)
d1 <- dcast(
        cSplit(df1, "optcode", ",", "long")[
           df2, on = c("optcode" ="obname")
             ][type == "", options := optcode], 
              ob + options ~type, value.var = "optcode")

按“ob”分组,我们删除每行的 NA 元素并将 (:=) 附加列“V1”分配给 NULL。

d1[, lapply(.SD, na.omit) , ob][, V1 := NULL][]
#      ob options apple grape melon orange
#1: alexa      NA    NA    tt    dd     NA
#2: dixon      pb    NA    NA    NA     NA
#3: flora      cc    bb    NA    NA     gg

数据

df1 <-  structure(list(ob = c("flora", "alexa", "dixon"), optcode = c("gg,bb,cc", 
"tt,dd", "pb")), .Names = c("ob", "optcode"), class = "data.frame", 
 row.names = c("1", "2", "3"))

df2 <- structure(list(obname = c("gg", "bb", "cc", "tt", "pb", "dd"), 
 type = c("orange", "apple", "", "grape", "", "melon")), .Names = c("obname", 
 "type"), class = "data.frame", row.names = c("1", "2", "3", "4", 
"5", "6"))

【讨论】:

  • 谢谢阿克伦。如果有一个值而不是缺失/空值,你将如何更改代码让我们说“无”。那我应该把这个“[type ==”,options := optcode]”部分代码拿出来吗?
  • @syebill 考虑到“类型”是character 类,我认为这会起作用。
  • 你能再看看吗。感谢您的帮助。
  • @syebill 我有疑问。在“nooption”列的输出中,dixon 不应该是“cc”
  • 你是对的。纠正。谢谢!对代码中需要更改的内容有什么想法吗?
【解决方案2】:

这是tidyr/dplyr 方法。 IMO 下面的方法非常简单,唯一的技巧是在合并df1 和df2 后处理缺失值(即NA's)。这是通过用 "options" 替换 type 中所有缺失的条目,然后删除 obn​​ame 的所有缺失条目来完成的。

library(tidyr)
library(stringr)
library(dplyr)

df2[df2$type=="", "type"] = NA #replacing blanks with NA, we need for merger later

df1 %>% 
  separate(optcode, into = paste0("opt", seq(1, max(str_count(.$optcode, ",")) + 1)), sep=",") %>% #the code passed to the into argument is a bit overkill, however, it generalizes to any number of elements contained in optcode
  gather(key, obname, -ob) %>%
  left_join(df2) %>%
  select(-key) %>%
  mutate(type = ifelse(is.na(type), "options", type)) %>% 
  filter(!is.na(obname)) %>%
  spread(type,obname)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 2020-09-20
    • 1970-01-01
    • 2021-05-12
    • 1970-01-01
    • 2021-03-21
    • 2023-03-25
    相关资源
    最近更新 更多