r - 结合 {stringr} 和 mutate() 在大型数据集中一次操作多个列?
问题描述
代表
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()
任何给定的变量。有没有更好、更省时的方法?
解决方案
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
输出。我在这里保持相同的名字。
推荐阅读
- list - Haskell:飞镖游戏
- powershell - 为什么我在这段代码中使用了太多的磁盘空间?
- javascript - 使用 jQuery .when,如何传入可变数量的函数调用?
- java - 如何为这种工厂模式使用 Guice Assisted Inject?
- java - Room SQL:使用两个表上的 WHERE 参数查询具有一对多关系的对象
- python - 名称“ImageDataBunch”未定义
- powershell - 从多个文本文件的大型数据集中收集唯一项目
- java - Java菜单栏隐藏背景图片
- angular - 如果需要与另一台服务器通信,如何构建我的 webapp?
- php - 在 Ubuntu / Nginx / Visual Studio Code 中使用 xdebug 时出错