r - 宽到长格式:如何在特定列之间进行平均(2 组列)
问题描述
我有一个宽格式的数据集,我想转换为长格式。宽格式的列表示一个长格式变量的两个级别。我想对宽格式的每组列进行逐行平均,并在汇总的长格式表中表示每组列的该值(平均值)。
虚拟数据
假设我有一项研究的数据,该研究测试了兽医如何给动物称重。有 10 名兽医(这些是“受试者”),每行一名。至于被称重的动物,有狗或猫(其中6种)。每个兽医都在诊所环境或家庭环境中测量所有动物。我想为每位兽医计算(1)他/她测量的所有狗的平均体重,以及(2)他/她测量的所有猫的平均体重。
library(tidyverse)
set.seed(123)
df <- data.frame(replicate(12,sample(10:25,10,rep=TRUE)))
id <- 1:10
clinic_vs_house <- sample(c(0,1), 10, replace = TRUE)
df <- cbind(id, clinic_vs_house, df)
names(df) <- c("id",
"location",
"cat_a",
"cat_b",
"cat_c",
"cat_d",
"cat_e",
"cat_f",
"dog_a",
"dog_b",
"dog_c",
"dog_d",
"dog_e",
"dog_f")
> df
## id location cat_a cat_b cat_c cat_d cat_e cat_f dog_a dog_b dog_c dog_d dog_e dog_f
## 1 1 0 24 13 18 18 24 21 14 15 23 15 18 25
## 2 2 1 24 23 21 23 25 14 17 14 15 11 13 23
## 3 3 0 12 15 18 12 19 16 21 24 20 10 15 21
## 4 4 0 23 18 18 13 22 14 24 18 17 11 18 24
## 5 5 0 12 19 22 23 16 20 22 24 15 13 25 18
## 6 6 1 19 20 12 10 18 25 11 19 15 22 23 23
## 7 7 1 11 25 17 20 18 15 10 21 16 14 18 23
## 8 8 0 15 14 19 16 19 18 18 24 24 15 16 25
## 9 9 0 20 12 16 14 16 11 20 25 25 24 12 12
## 10 10 0 14 20 19 21 20 22 18 13 10 12 17 23
我目前笨拙的解决方案
我创建了两个单独的数据框,每个数据框用于一组不同的动物,我在其中计算相关列的平均值。然后我合并了表格。
cat_means <-
df %>%
mutate(mean_wt = rowMeans(select(., matches("cat")))) %>%
select(id, location, mean_wt) %>%
mutate(animal = "cat")
dog_means <-
df %>%
mutate(mean_wt = rowMeans(select(., matches("dog")))) %>%
select(id, location, mean_wt) %>%
mutate(animal = "dog")
means_table <-
bind_rows(cat_means, dog_means) %>%
select(id, location, animal, mean_wt) %>%
arrange(id)
> means_table
## id location animal mean_wt
## 1 1 0 cat 16.85714
## 2 1 0 dog 18.33333
## 3 2 1 cat 18.71429
## 4 2 1 dog 15.50000
## 5 3 0 cat 13.14286
## 6 3 0 dog 18.50000
## 7 4 0 cat 15.42857
## 8 4 0 dog 18.66667
## 9 5 0 cat 16.00000
## 10 5 0 dog 19.50000
## 11 6 1 cat 15.00000
## 12 6 1 dog 18.83333
## 13 7 1 cat 15.28571
## 14 7 1 dog 17.00000
## 15 8 0 cat 14.42857
## 16 8 0 dog 20.33333
## 17 9 0 cat 12.71429
## 18 9 0 dog 19.66667
## 19 10 0 cat 16.57143
## 20 10 0 dog 15.50000
所以是的,我能够得到我想要的结果,但我对这个解决方案不满意,因为它是重复的代码,如果我有不止 2 组要转换的列,那将是一个痛苦。有没有更简洁的方法来获得相同的结果?我知道我总是可以编写一个运行 x 次的函数,但我想知道是否有一个我不知道的更优雅的解决方案,尤其是使用tidyverse
.
解决方案
df %>%
pivot_longer(cols=cat_a:dog_f, names_pattern = "(.*)_(.*)", names_to=c("animal","letter")) %>%
group_by(id, location, animal) %>%
summarise(mean_wt=mean(value))
# A tibble: 20 x 4
# Groups: id, location [10]
id location animal mean_wt
<int> <dbl> <chr> <dbl>
1 1 0 cat 19.7
2 1 0 dog 18.3
3 2 1 cat 21.7
4 2 1 dog 15.5
5 3 0 cat 15.3
6 3 0 dog 18.5
7 4 0 cat 18
8 4 0 dog 18.7
9 5 0 cat 18.7
10 5 0 dog 19.5
11 6 1 cat 17.3
12 6 1 dog 18.8
13 7 1 cat 17.7
14 7 1 dog 17
15 8 0 cat 16.8
16 8 0 dog 20.3
17 9 0 cat 14.8
18 9 0 dog 19.7
19 10 0 cat 19.3
20 10 0 dog 15.5
推荐阅读
- android - 在 Play 商店更新新应用后,它只显示旧版本
- eclipse - Dbpedia 和 Wikidata 上的联合查询
- flutter - Flutter:如何检查对象是否是类的实例(有状态或无状态小部件)
- jquery - JQuery - 无法用新名称更新现有名称
- javascript - 拆分日期范围重叠成块(javascript)
- java - 我的应用程序我想将一些测试显示为 url 链接,因为当我们键入或复制粘贴 url 时,watspp 会显示
- xamarin.forms - 扫描条码时使用手电筒
- android - 如何获取特定字符串格式的日期完整时间
- c# - 设计视图模型并避免在控制器中使用 if else 语句并使用设计模式编写良好的业务逻辑 asp.net web api
- django - Django:如何在 sqlite3 数据库中添加/删除字段?