【问题标题】:Using tidyverse to dynamically mutate one variable from one grouped dataset from another dataset使用 tidyverse 从一个分组数据集中动态变异另一个数据集中的一个变量
【发布时间】:2020-06-04 06:22:32
【问题描述】:

假设我使用不同的课程(我的数据集中的节点)并且我有成千上万的学生。每个学生都有自己的数学成绩,我需要将所有个人成绩与小组均值/标准差进行比较。 为了解决这个问题,我有两个不同的数据集。第一个是“一张桌子”。

这个数据框由几个类(节点)、它们的平均值和它们的 sd 组成。

我还有另一个由学生成绩组成的数据集,比如这个:

我想要另一个数据集,在其中我得到所有单独的结果(即 11、6、10 等),并从第一个数据集中的所有平均值中减去这个结果。将来,需要将所有结果和所有节点一起检查。

换句话说,从第一个名字(图像中的数字 12),我将从 68(平均结果)中减去 11(学生的结果),从 68(平均)中减去 6(学生的结果),10(学生的结果)从 68(平均值)等 然后我将移动到第二个节点(图像中的数字 7),我也会这样做(从 74 中减去 11(平均结果),从 74 中减去 6(平均结果),从 74 中减去 10),

我想要的最终输出如下。请将此图像仅用作说明:

由于问题,为了让我的问题更清楚,以下命令也带来了一个有趣的解决方案,但它不起作用,因为我必须手动将所有列添加到新数据集中:

test_result %>% 
  mutate(total_header_node_12 = x - default_table$t_mean[1]) %>% 
  mutate(total_header_node_74 = x - default_table$t_mean[2]) 

我搜索了其他问题,但没有找到任何解决方案。 任何帮助都是有价值的。我使用 tidyverse,我想留在 tidyverse 环境中。 谢谢 复制:

> dput(default_table)
structure(list(node = structure(c(6L, 3L, 5L, 1L, 2L, 4L, 7L), .Label = c("4", 
"5", "7", "8", "10", "12", "13"), class = "factor"), t_mean = c(68.8219178082192, 
74.3260869565217, 83.0178571428571, 92.2108108108108, 98.3304347826087, 
88.6111111111111, 48.4), t_sd = c(14.4351088961341, 16.9448394654941, 
13.0272663858681, 12.2011483603603, 12.1775472144027, 14.5621088567959, 
10.4876948807826), vars = c(1, 1, 1, 1, 1, 1, 1), n = c(121, 
74, 92, 616, 191, 58, 7), mean = c(68, 74.6891891891892, 82.8369565217391, 
91.3944805194805, 97.738219895288, 88.0172413793103, 48.7142857142857
), sd = c(14.0226008048911, 16.1151045250761, 11.0426517498479, 
12.6758935948866, 12.0212336250146, 15.9169901273025, 8.63547500554709
), min = c(32, 32, 58, 36, 56, 44, 39), max = c(97, 113, 104, 
123, 128, 124, 60), range = c(65, 81, 46, 87, 72, 80, 21), se = c(1.27478189135374, 
1.87334284914993, 1.15127602962793, 0.510726307415094, 0.869825937534791, 
2.09000319547951, 3.26390275965596), q0_25 = c(59, 64, 74.75, 
84, 90, 80, 41.5), q0_5 = c(68, 73.5, 81.5, 92, 98, 87, 47), 
    q0_75 = c(80, 87.75, 92.25, 100, 106, 98.75, 56)), class = "data.frame", row.names = c(NA, 
-7L))


test_result <- data.frame(x = rnorm(100,10,2))

【问题讨论】:

  • R和excel截图中的数字匹配吗?
  • 不,excel 只是我想要的预览。完全没有关系。
  • @CalumYou,实际上,我没有这个变量。我可以压制这些信息,只拥有价值。谢谢
  • 所以学生在 excel 中的结果与 R 中的 test_result$x 匹配?
  • Excel 中的这张图片仅供参考。在这种情况下,它匹配,但它只是为了显示所需的输出。我将编辑问题以明确我的问题。谢谢

标签: r loops iteration tidyverse dplyr


【解决方案1】:

或许,你可以试试:

library(dplyr)

default_table %>%
  tidyr::crossing(test_result) %>%
  mutate(comparative_mean = x - t_mean)

这会创建default_tabletest_result 的所有组合,然后我们将这两个值相减。

【讨论】:

  • 我印象深刻!我不知道 tidyverse 有这个功能!!
【解决方案2】:

您只需将学生成绩添加为新列,然后添加unnest 即可获得可以进行此比较的长表单数据。 crossing 可能还有一个解决方案,但这似乎更简单。本质上,我们希望将学生结果作为新列插入default_table,然后使用unnest 展开,以便每个节点学生有一行,如所需的输出所示。然后我们可以简单地从学生成绩中减去平均值。

set.seed(1)
library(tidyverse)
default_table <- structure(list(node = structure(c(6L, 3L, 5L, 1L, 2L, 4L, 7L), .Label = c("4", "5", "7", "8", "10", "12", "13"), class = "factor"), t_mean = c(68.8219178082192, 74.3260869565217, 83.0178571428571, 92.2108108108108, 98.3304347826087, 88.6111111111111, 48.4), t_sd = c(14.4351088961341, 16.9448394654941, 13.0272663858681, 12.2011483603603, 12.1775472144027, 14.5621088567959, 10.4876948807826), vars = c(1, 1, 1, 1, 1, 1, 1), n = c(121, 74, 92, 616, 191, 58, 7), mean = c(68, 74.6891891891892, 82.8369565217391, 91.3944805194805, 97.738219895288, 88.0172413793103, 48.7142857142857), sd = c(14.0226008048911, 16.1151045250761, 11.0426517498479, 12.6758935948866, 12.0212336250146, 15.9169901273025, 8.63547500554709), min = c(32, 32, 58, 36, 56, 44, 39), max = c(97, 113, 104, 123, 128, 124, 60), range = c(65, 81, 46, 87, 72, 80, 21), se = c(1.27478189135374, 1.87334284914993, 1.15127602962793, 0.510726307415094, 0.869825937534791, 2.09000319547951, 3.26390275965596), q0_25 = c(59, 64, 74.75, 84, 90, 80, 41.5), q0_5 = c(68, 73.5, 81.5, 92, 98, 87, 47), q0_75 = c(80, 87.75, 92.25, 100, 106, 98.75, 56)), class = "data.frame", row.names = c(NA, -7L))
test_result <- data.frame(x = rnorm(10,10,2))

test_result <- test_result %>%
  rowid_to_column(var = "student_number") %>%
  rename(student_result = x)

default_table %>%
  mutate(students = map(node, ~ test_result)) %>%
  unnest(students) %>%
  mutate(comparative_mean = student_result - mean) %>%
  select(node, mean, student_number, student_result, comparative_mean)
#> # A tibble: 70 x 5
#>    node   mean student_number student_result comparative_mean
#>    <fct> <dbl>          <int>          <dbl>            <dbl>
#>  1 12       68              1           8.75            -59.3
#>  2 12       68              2          10.4             -57.6
#>  3 12       68              3           8.33            -59.7
#>  4 12       68              4          13.2             -54.8
#>  5 12       68              5          10.7             -57.3
#>  6 12       68              6           8.36            -59.6
#>  7 12       68              7          11.0             -57.0
#>  8 12       68              8          11.5             -56.5
#>  9 12       68              9          11.2             -56.8
#> 10 12       68             10           9.39            -58.6
#> # … with 60 more rows

reprex package (v0.3.0) 于 2020 年 2 月 19 日创建

【讨论】:

  • 能否请您解释(或链接以获取教程) mutate(students = map(node, ~ test_result)) %>% unnest(students) 部分。当我创建“学生”(通过变异然后映射)时,R 在幕后做什么?您的解决方案非常优雅。
  • map 将函数应用于向量并返回相同长度的列表。这里我只选择node并使用紧凑函数语法~ test_result,相当于function() {test_result},即无论输入如何,它都只返回test_result表。
猜你喜欢
  • 2017-01-10
  • 1970-01-01
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
  • 1970-01-01
  • 2019-06-17
相关资源
最近更新 更多