0

我在 R 中有一个数据框,如下所示。

test <- data.frame("FRUITSTRING" = c("APPLE_PEAR_BANANA",
                                     "TURNIP_CABBAGE_ORANGE_PEAR_BANANA",
                                     "APPLE_CARROT_PEAR_BANANA"), 
                   "SPLIT_CHAR" = c("PEAR","ORANGE","PEAR"))

我希望将 FRUITSTRING 列拆分为两列,但根据名为 SPLIT_CHAR 的第二列的值逐行拆分。是否有可能做到这一点?注意字符串长度可以改变,分割字符的位置可以改变,这就是为什么我想调用一个特定的字符来进行分割。

我之前使用的函数是 cSplit,但是我不知道如何将此数据帧传递到 cSplit 并使用另一列的阀门作为 csplit 的输入。谢谢

4

1 回答 1

1

1) dplyr/stsringr/tidyr将 SPLIT_CHAR 字符串和周围的 _ 替换为分号,然后用分号分隔。

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

test %>%
  mutate(FRUITSTRING = str_replace(FRUITSTRING, str_c("_", SPLIT_CHAR, "_"), ";")) %>%
  separate(FRUITSTRING, c("prefix", "suffix"), sep = ";")
##           prefix      suffix SPLIT_CHAR
## 1          APPLE      BANANA       PEAR
## 2 TURNIP_CABBAGE PEAR_BANANA     ORANGE
## 3   APPLE_CARROT      BANANA       PEAR

2) Base R - transform/sub或使用 base R。提取前缀并使用 sub 单独提取后缀。因为我们需要一个矢量化版本的 sub 在一开始就定义了它。如果要保留 FRUITSTRING,则省略 transform 的最后一个参数。

vsub <- Vectorize(sub)
transform(test,
 prefix = vsub(paste0("_", SPLIT_CHAR, "_.*"), "", FRUITSTRING),
 suffix = vsub(paste0(".*_", SPLIT_CHAR, "_"), "", FRUITSTRING),
 FRUITSTRING = NULL)
##   SPLIT_CHAR         prefix      suffix
## 1       PEAR          APPLE      BANANA
## 2     ORANGE TURNIP_CABBAGE PEAR_BANANA
## 3       PEAR   APPLE_CARROT      BANANA

2a) within/sub或相同但使用 within 和稍微不同的正则表达式模式,以便我们可以对 sub 的两个实例使用相同的模式。

vsub <- Vectorize(sub)
within(test, {
  pat <- paste0("(.*)_", SPLIT_CHAR, "_(.*)")
  suffix <- vsub(pat, "\\2", FRUITSTRING)
  prefix <- vsub(pat, "\\1", FRUITSTRING)
  FRUITSTRING <- pat <- NULL
})
##   SPLIT_CHAR         prefix      suffix
## 1       PEAR          APPLE      BANANA
## 2     ORANGE TURNIP_CABBAGE PEAR_BANANA
## 3       PEAR   APPLE_CARROT      BANANA

3) cSplit 与 (1) 中一样,将 SPLIT_CHAR 字符串和周围的 _ 替换为分号,然后以分号拆分。

library(splitstackshape)

test |>
  transform(FRUITSTRING = 
      Vectorize(sub)(paste0("_", SPLIT_CHAR, "_"), ";", FRUITSTRING)) |>
  cSplit("FRUITSTRING", sep = ";", type.convert = FALSE)
##    SPLIT_CHAR  FRUITSTRING_1 FRUITSTRING_2
## 1:       PEAR          APPLE        BANANA
## 2:     ORANGE TURNIP_CABBAGE   PEAR_BANANA
## 3:       PEAR   APPLE_CARROT        BANANA
于 2021-07-27T12:23:24.013 回答