r - 使用 tidyverse 根据索引链接的第三列中的值从另一列生成新列输入值
问题描述
我有一个看起来像这样的数据框(但有数百列):
df_in <-
data.frame(
x_1 = 0:3,
x_2 = 30:33,
x_3 = 20:23,
y_1 = c("a", "c", "b", "c"),
y_2 = c("b", "a", "c", "b"),
y_3 = c("c", "b", "a", "a"))
假设 y 列包含运动队的名称(a、b、c);x 变量,通过列索引号与 y 变量相关联,是球队进球数;每一行代表一个 3 路比赛。
对于每场比赛,我想创建新的列来记录两个团队 a 和 b 的表现。这是我想要的输出,使用长期方法:
df_in %>%
mutate(
a_value =
case_when(
y_1 == "a" ~ x_1,
y_2 == "a" ~ x_2,
y_3 == "a" ~ x_3),
b_value =
case_when(
y_1 == "b" ~ x_1,
y_2 == "b" ~ x_2,
y_3 == "b" ~ x_3))
鉴于实际数据中有更多列,我需要使其更简洁。我猜有一种 tidyverse 方法可以做到这一点,但我不确定。
解决方案
乍一看比我想象的要复杂一些。我给每个匹配一个 ID,这样你就可以(没有双关语)根据原始行匹配值。第一步是重塑,以便获得一个变量(x 或 y)和一个索引(1、2、3、...)。重塑回宽会让你得到你的a_value
和b_value
列(我没有放弃团队 c 的观察,因为你说这需要扩展)。然后通过匹配将其连接回原始数据帧。您可以一步完成所有连接(类似于 SQL 子查询),但这有点混乱。
library(tidyr)
df_in <- tibble::rowid_to_column(df_in, "match")
team_vals <- df_in %>%
pivot_longer(-match, names_to = c(".value", "index"), names_pattern = "(^[a-z])_(\\d$)") %>%
pivot_wider(id_cols = match, names_from = y, values_from = x, names_glue = "{y}_value")
team_vals
#> # A tibble: 4 × 4
#> match a_value b_value c_value
#> <int> <int> <int> <int>
#> 1 1 0 30 20
#> 2 2 31 21 1
#> 3 3 22 2 32
#> 4 4 23 33 3
dplyr::left_join(df_in, team_vals, by = "match")
#> match x_1 x_2 x_3 y_1 y_2 y_3 a_value b_value c_value
#> 1 1 0 30 20 a b c 0 30 20
#> 2 2 1 31 21 c a b 31 21 1
#> 3 3 2 32 22 b c a 22 2 32
#> 4 4 3 33 23 c b a 23 33 3
推荐阅读
- python - 如何返回更改后的 Python numpy 数组大小参考参数
- c# - 未注册类型“Microsoft.AspNetCore.Mvc.ViewFeatures.PartialViewResultExecutor”的服务
- python - Python ctypes Windows 操作 - 脚本在 64 位解释器中失败,但在 32 位解释器中工作正常
- java - 是什么让子类(即 RuntimeException 未选中而异常被选中)成为可能?
- python - Pandas DataFrame,不能使用内置函数 - 不支持的操作数类型
- pytorch - What are Torch Scripts in PyTorch?
- python - 用 Python 制作砖块
- vba - .Outlook VBA 中的正文没有收到纯文本电子邮件的文本
- javascript - 提供适合用户连接的视频资产?
- python - 使用 python 在 Visual Studio 中出现不必要的缩进错误