根据字符串拆分数据帧

时间:2020-02-24 12:12:24

标签: r dataframe split

我想根据每个元素的最终编号分割以下数据帧。所以我想要6个新数据帧,每个数据帧包含两个元素。这是我尝试获取仅包含“ ABCD-1”和“ ABCC-1”的第一个子集的数据帧的方法,但似乎不起作用。

{{1}}

可以帮忙吗?

谢谢

阿比盖尔

3 个答案:

答案 0 :(得分:3)

主要思想是创建一个用于定义拆分分组的因子。一种方法是使用正则表达式从提供的变量Barcode中提取数字模式。然后,我们用as.factor()将获得的数字字符向量转换为因子。 当然,我们可以使用其他正则表达式技术来完成工作,或者使用stringr包中的更多用户友好的包装函数,就像第二个示例中一样(tidyverse-ish方法)。 / p>

示例1

使用split的基本R解决方案:

# The provided data
Barcode <- c("ABCD-1", "ABCC-1", "ABCD-2", "ABCC-2", "ABCD-3", "ABCC-3", 
             "ABCD-4", "ABCC-4", "ABCD-5", "ABCC-5","ABCD-6", "ABCC-6")
bar_f <- data.frame(Barcode)

factor_for_split <- regmatches(x = bar_f$Barcode,
                               m = regexpr(pattern = "[[:digit:]]",
                                           text = bar_f$Barcode))
factor_for_split
#>  [1] "1" "1" "2" "2" "3" "3" "4" "4" "5" "5" "6" "6"

# Create a list of 6 data frames as asked
lst <- split(x = bar_f, f = as.factor(factor_for_split))
lst
#> $`1`
#>   Barcode
#> 1  ABCD-1
#> 2  ABCC-1
#> 
#> $`2`
#>   Barcode
#> 3  ABCD-2
#> 4  ABCC-2
#> 
#> $`3`
#>   Barcode
#> 5  ABCD-3
#> 6  ABCC-3
#> 
#> $`4`
#>   Barcode
#> 7  ABCD-4
#> 8  ABCC-4
#> 
#> $`5`
#>    Barcode
#> 9   ABCD-5
#> 10  ABCC-5
#> 
#> $`6`
#>    Barcode
#> 11  ABCD-6
#> 12  ABCC-6

# Edit names of the list
names(lst) <- paste0("df_", names(lst))

# Assign each data frame from the list to a data frame object in the global
# environment
for(name in names(lst)) {
  assign(name, lst[[name]])
}

reprex package(v0.3.0)于2020-02-24创建

示例2

而且,如果您愿意,这是一种tidyverse式的方法:

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(stringr)

Barcode <- c("ABCD-1", "ABCC-1", "ABCD-2", "ABCC-2", "ABCD-3", "ABCC-3", 
             "ABCD-4", "ABCC-4", "ABCD-5", "ABCC-5","ABCD-6", "ABCC-6")
bar_f <- data.frame(Barcode)

bar_f %>% 
  mutate(factor_for_split = str_extract(string = Barcode,
                                        pattern = "[[:digit:]]")) %>% 
  group_split(factor_for_split)
#> [[1]]
#> # A tibble: 2 x 2
#>   Barcode factor_for_split
#>   <fct>   <chr>           
#> 1 ABCD-1  1               
#> 2 ABCC-1  1               
#> 
#> [[2]]
#> # A tibble: 2 x 2
#>   Barcode factor_for_split
#>   <fct>   <chr>           
#> 1 ABCD-2  2               
#> 2 ABCC-2  2               
#> 
#> [[3]]
#> # A tibble: 2 x 2
#>   Barcode factor_for_split
#>   <fct>   <chr>           
#> 1 ABCD-3  3               
#> 2 ABCC-3  3               
#> 
#> [[4]]
#> # A tibble: 2 x 2
#>   Barcode factor_for_split
#>   <fct>   <chr>           
#> 1 ABCD-4  4               
#> 2 ABCC-4  4               
#> 
#> [[5]]
#> # A tibble: 2 x 2
#>   Barcode factor_for_split
#>   <fct>   <chr>           
#> 1 ABCD-5  5               
#> 2 ABCC-5  5               
#> 
#> [[6]]
#> # A tibble: 2 x 2
#>   Barcode factor_for_split
#>   <fct>   <chr>           
#> 1 ABCD-6  6               
#> 2 ABCC-6  6               
#> 
#> attr(,"ptype")
#> # A tibble: 0 x 2
#> # ... with 2 variables: Barcode <fct>, factor_for_split <chr>

names(lst) <- paste0("df_", 1:length(lst))
for(name in names(lst)) {
  assign(name, lst[[name]])

reprex package(v0.3.0)于2020-02-24创建

答案 1 :(得分:1)

您可以尝试

library(tidyverse)
separate(bar_f, Barcode, into = letters[1:2], sep ="-")

完整的tidyvers方式可能看起来像

bar_f %>% 
  separate(Barcode, into = letters[1:2], sep ="-") %>% 
  filter(b == 1)
     a b
1 ABCD 1
2 ABCC 1

在基础R中,您可以尝试使用gsub来删除字母和字母以及-

bar_f$SampleID <- gsub("[aA-zZ|-]","",bar_f$Barcode)
head(bar_f)
  Barcode SampleID
1  ABCD-1        1
2  ABCC-1        1
3  ABCD-2        2
4  ABCC-2        2
5  ABCD-3        3
6  ABCC-3        3

答案 2 :(得分:1)

这是另一个使用内置函数的解决方案:

dfs <- split(bar_f, gsub("\\D", "", DT$Barcode))
names(dfs) <- paste0("df_", names(dfs))

for(nm in names(dfs)) assign(nm, dfs[[nm]])