r - 提取部分字符串值,创建新的列名,并使数据框变宽

标签 r regex dplyr

我想提取字符串列的最后一部分(总是包含在方括号中),将这些作为新列的名称,然后将数据从长到宽重新整形,并用这些值填充新列。

例如,如果我有这个数据框:

whatihave <- data_frame(v1 = c('abc [effort]', 'def [effort]', 'ghi [effort]', 'abc [scope]', 'def [scope]', 'ghi [scope]'),
                        scores = c(1:6))

# A tibble: 6 x 2
  v1           scores
  <chr>         <int>
1 abc [effort]      1
2 def [effort]      2
3 ghi [effort]      3
4 abc [scope]       4
5 def [scope]       5
6 ghi [scope]       6

我想把它转换成这个数据框:

whatiwant <- data_frame(v1 = c('abc', 'def', 'ghi'), 
                        effort = c(1, 2, 3),
                        scope = c(4, 5, 6))

  v1    effort scope
  <chr>  <dbl> <dbl>
1 abc        1     4
2 def        2     5
3 ghi        3     6

如您所见,v1 列中值末尾方括号内的字符已成为两个新变量的名称(effort范围)。 scores 列中的值随后填充了我创建的新列。

我该怎么做?

在下方编辑

我模拟的玩具数据缺少实际数据的一个关键特征。实际上有多个实例具有相同的 v1 值并且在方括号中具有相同的后缀。

因此,下面的答案(否则非常好)会在 effortscope 的每个单元格中生成列列表,而不是单个值。

让我们假设我有这些数据:

whatiactuallyhave <- data_frame(v1 = c('abc [effort]', 'abc [effort]', 'def [effort]', 'def [effort]', 'ghi [effort]', 'abc [scope]', 'abc [scope]', 'def [scope]', 'ghi [scope]', 'ghi [scope]'), 
                        scores = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'))

# A tibble: 10 x 2
   v1           scores
   <chr>        <chr> 
 1 abc [effort] 1     
 2 abc [effort] 2     
 3 def [effort] 3     
 4 def [effort] 4     
 5 ghi [effort] 5     
 6 abc [scope]  6     
 7 abc [scope]  7     
 8 def [scope]  8     
 9 ghi [scope]  9     
10 ghi [scope]  10    

我想把它变成这样:

whatiactuallywant <- data_frame(v1 = c('abc', 'abc', 'def', 'def', 'ghi', 'ghi'), 
                        effort = c('1', '2', '3', '4', '5', 'NA'),
                        scope = c('6', '7', '8', 'NA', '9', '10'))

# A tibble: 6 x 3
  v1    effort scope
  <chr> <chr>  <chr>
1 abc   1      6    
2 abc   2      7    
3 def   3      8    
4 def   4      NA   
5 ghi   5      9    
6 ghi   NA     10   

我希望现在更清楚了!非常感谢您的帮助。

最佳答案

修改后的场景

  • 使用 tidyr::extract 将让您节省一个额外的 mutate 步骤,因为您可以在此处使用 regex 直接将两个所需的字符串提取到两列中。
library(tidyverse)
whatiactuallyhave <- data_frame(v1 = c('abc [effort]', 'abc [effort]', 'def [effort]', 'def [effort]', 'ghi [effort]', 'abc [scope]', 'abc [scope]', 'def [scope]', 'ghi [scope]', 'ghi [scope]'), 
                                scores = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'))
#> Warning: `data_frame()` was deprecated in tibble 1.1.0.
#> Please use `tibble()` instead.

whatiactuallyhave %>%
  tidyr::extract(v1, into = c('v1', 'name'), regex = '(\\w+)\\s\\[(\\w+)\\]') %>%
  group_by(v1, name) %>%
  mutate(d = row_number()) %>%
  pivot_wider(names_from = name, values_from = scores, values_fill = NA) %>%
  select(-d)

#> # A tibble: 6 x 3
#> # Groups:   v1 [3]
#>   v1    effort scope
#>   <chr> <chr>  <chr>
#> 1 abc   1      6    
#> 2 abc   2      7    
#> 3 def   3      8    
#> 4 def   4      <NA> 
#> 5 ghi   5      9    
#> 6 ghi   <NA>   10

reprex package 创建于 2021-05-26 (v2.0.0)


较早的回答

whatihave <- data_frame(v1 = c('abc [effort]', 'def [effort]', 'ghi [effort]', 'abc [scope]', 'def [scope]', 'ghi [scope]'),
                        scores = c(1:6))

library(tidyverse)
whatihave %>%
  separate(v1, into = c('v1', 'name'), sep = ' \\[') %>%
  mutate(name = str_remove(name, '\\]')) %>%
  pivot_wider(names_from = name, values_from = scores)


# A tibble: 3 x 3
  v1    effort scope
  <chr>  <int> <int>
1 abc        1     4
2 def        2     5
3 ghi        3     6

关于r - 提取部分字符串值,创建新的列名,并使数据框变宽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67707999/

相关文章:

r - 标记分组间隔的游程长度

r - 在 R 中跨行 data.table 查找模式

r - RStudio 中的 Sweave 找不到全局环境中加载的对象

Python re.sub 查询解析

javascript - 检查文本是否以字符开头,后跟数字

r - tidyverse:汇总时计算特定级别的数量

r - 在 R 表达式中查找所有函数的名称

r - ggplot 无法绘制最小点

c++ - 源代码注释的正则表达式

r - 组的滞后变量在 dplyr 中不起作用