【问题标题】:Combine {stringr} and mutate() to manipulate multiple columns at once in large dataset?结合 {stringr} 和 mutate() 在大型数据集中一次操作多个列?
【发布时间】:2021-03-23 22:43:23
【问题描述】:

Reprex

df <- tibble(name = c("Person_1","Person_2","Person_3"),
             `AxxBxx1:0` = c("1:04","2:02","0:1"),
             `AxxCxx5:0` = c("5:04","3:02","0:0"),
             `BxxCxx2:1` = c("2:14","1:03","0:1"))

目标是将这个data.frame转换成另一个,其中以_real结尾的变量取自列名,_bet和_result取自df的第一部分和第二部分的变量值:

df_2 <- tibble(name = c("Person_1","Person_2","Person_3"),
               AxxBxx_real = "1:0",
               AxxCxx_real = "5:0",
               BxxCxx_real = "2:1",
               AxxBxx_bet = c("1:0","2:0","0:1"),
               AxxCxx_bet = c("5:0","3:0","0:0"),
               BxxCxx_bet = c("2:1","1:0","0:1"),
               AxxBxx_result = c("4","2",""),
               AxxCxx_result = c("4","2",""),
               BxxCxx_result = c("4","3",""))

问题:真正的数据集比df 大得多,理想情况下,我希望尽可能自动化地将df 转换为df_2。

代码(即我到目前为止所做的)

library(tidyverse)

# Step 1: Get real match results from variable names.
df$AxxBxx_real <- "1:0"
df$AxxCxx_real <- "5:0"
df$BxxCxx_real <- "2:1"

有没有办法将mutate() 中的原始变量从df 一次性变成这三个_real 变量,而无需查找单独的匹配结果? mutate(names(df)[2:4] = str_extract(...)) 或类似的东西显然不起作用。

# Create `_bet` and `_result` variables.
str_remove(names(df)[2:4], "[0-99]:[0-99]") %>%
  paste0("_bet") -> names(df)[2:4]

df %>%
  mutate(AxxBxx_result = AxxBxx_bet,
         AxxCxx_result = AxxCxx_bet,
         BxxCxx_result = BxxCxx_bet) -> df

df$AxxBxx_bet <- str_extract(df$AxxBxx_bet, "[0-99]:[0-99]")
df$AxxCxx_bet <- str_extract(df$AxxCxx_bet, "[0-99]:[0-99]")
df$BxxCxx_bet <- str_extract(df$BxxCxx_bet, "[0-99]:[0-99]")

df$AxxBxx_result <- str_remove(df$AxxBxx_result, "[0-99]:[0-99]")
df$AxxCxx_result <- str_remove(df$AxxCxx_result, "[0-99]:[0-99]")
df$BxxCxx_result <- str_remove(df$BxxCxx_result, "[0-99]:[0-99]")

这里的问题是,虽然从 data.frame 中每个人的赌注结果中拆分赌注的过程在某种程度上是标准化的,但创建和存储新变量的方式却不是。我不想单独对每个变量执行此操作,而是希望自动完成此操作。取原始变量的名称并从它们的名称中删除结果,然后拆分为_bet 和_real。同样,问题是我一次只能mutate() 任何给定变量。有没有更好、更省时的方法?

【问题讨论】:

    标签: r stringr dplyr


    【解决方案1】:

    这是使用tidyr library 的一种方法:

    这将获取长格式的数据,将列名分为两部分,使用extract 我们将值分成两列,最后以宽格式获取数据。

    我建议您一次运行这一步,以了解这里发生了什么。

    library(tidyr)
    
    df %>%
      pivot_longer(cols = -name, 
                   names_to = c('col1', 'real'), 
                   names_pattern = '([A-Za-z]+)(\\d+:\\d+)') %>%
      extract(value, c('bet', 'result'), '(\\d+:.)(.)?') %>%
      pivot_wider(names_from = col1, values_from = c(real, bet, result), 
                  names_glue = '{col1}_{.value}')
    
    #  name     AxxBxx_real AxxCxx_real BxxCxx_real AxxBxx_bet AxxCxx_bet BxxCxx_bet AxxBxx_result AxxCxx_result BxxCxx_result
    #  <chr>    <chr>       <chr>       <chr>       <chr>      <chr>      <chr>      <chr>         <chr>         <chr>        
    #1 Person_1 1:0         5:0         2:1         1:0        5:0        2:1        "4"           "4"           "4"          
    #2 Person_2 1:0         5:0         2:1         2:0        3:0        1:0        "2"           "2"           "3"          
    #3 Person_3 1:0         5:0         2:1         0:1        0:0        0:1        ""            ""            ""      
    

    我不知道为什么name 会从输入中的Person_1、Person_2、Person_3 变为输出中的A、B 和C。我在这里保持相同的名称。

    【讨论】:

    • 谢谢,我已经在考虑将其转为长格式,而我需要的是提取、粘合等。
    • 另外,我在问题中修复了这个 A、B、C 问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 2012-07-30
    • 2011-01-21
    • 2014-12-19
    • 2021-09-30
    • 1970-01-01
    相关资源
    最近更新 更多