【发布时间】:2019-01-26 22:16:53
【问题描述】:
编辑:我稍微改变了原始问题的代表,因为它没有产生与我实际使用类似的示例。
这是对上一个问题recode/replace multiple values in a shared data column to a single value across data frames 的扩展,它非常适合更简单的应用程序。我尝试将解决方案扩展到稍微复杂的情况,但无济于事。
我有许多不同的数据框,所有这些数据框都有一些共享列(下面的 repex 中的“site”和“grp”)。在每个数据帧中,在“grp”变量中存在多个错误,一些共享一些错误。在上一个问题中,这是使用 tidyverse 和 recode 函数解决的,方法是创建一个键/值元素的 list 并使用
keyval <- setNames(rep(good_values, lengths(bad_values)), unlist(bad_values))
out <- map(df_list, ~ .x %>%
mutate(grp = recode_factor(grp, !!! keyval)))
但是,当键/值列表依赖于另一个共享变量“站点”的值时,我想这样做。例如,当站点 = s1 时 grp = a1 应重新编码为 grp = a,当站点 = s2 时应重新编码为 grp = f。我已经尝试使用map() 扩展上述代码,并在下面的示例中嵌套调用pmap():
#example data frames
library(tidyverse)
df1 = data.frame(site = c(rep("s1",5), rep("s2",5), rep("s3",5)),grp = c("a1","a.","a.",rep("b",4),"b2","b-","bq",rep("a1",5)), measure = rnorm(15))
df2 = data.frame(site = c(rep("s1",10), rep("s2",16), rep("s3",5)), grp = c(rep("as", 3), "b2",rep("a",22),rep("a1",5)), measure2 = rnorm(31))
df3 = data.frame(site = c(rep("s1",3), rep("s2",6), rep("s3",5)),grp = c(rep("b-",3),rep("bq",2),"a", rep("a.", 3),rep("a1",5)), measure3 = 1:14)
df_list = list(df1, df2, df3)
site_list = c("s1","s2","s3")
bad_values = list(c("a1","a.","as", "b2", "b-", "bq"),
c("a1","a.","as","b", "b2", "b-", "bq"),
c("a1"))
good_values = list(c("a", "a1","a2","b","b1","b2"),
c("f","f1","f2","g","g","g1","g2"),
c("t"))
#put dfs into list to `map` over
df_list = list(df1, df2, df3)
#what I tried.
#nested pmap() within map()
dfs_mod = map(df_list, ~.x %>%
pmap(list(site_list,bad_values,good_values),
~mutate(.x, grp = ifelse(site == ..1,recode(grp, !!!setNames(as.list(..2),..3)),grp))))
目前这会引发错误代码“错误:不知道如何从一种语言中提取”。搜索此错误,我无法理解错误是什么或如何完成任务。
编辑:我试过了也试过了
keyval = map2(good_values, bad_values, ~setNames(as.list(..1),unlist(..2)))
#this creates 3 lists of key/val elements to recode grp on for each site
dfs_mod = map(df_list, function(x){
map2(site_list, keyval, ~mutate(x, grp = ifelse(site == ..1, recode_factor(grp, !!!..2), grp)))
})
这不会引发错误,但也不能完全实现我想要的。它有几个不受欢迎的副作用:1)它创建了 3 个包含 3 个数据帧的列表,为每个 key/val 列表重新编码了一个 df 和 2)它将因子“grp”重新编码为一个整数(这让我感到困惑)。越来越清楚的是,我误解了 map*() 的用途,并且不喜欢使用它。因此,任何其他迭代地完成此任务的方法都将受到欢迎。
我想预期的输出可能是list,长度与 df_list 相同(在本例中为 3)。 'grp' variables = 'bad_values' 应重新编码为 'good_values',具体取决于列表元素位置和“站点”(例如 bad_values[[1]][1] -> good_values[[1]][1 ]、bad_values[[1]][2] -> good_values[[1]][2] 等,用于 site = site_list[[1]])。 'dfs_mod' list 中的第一个数据框应该是这样的:
dfs_mod[[1]]
site grp measure
1 s1 a -1.2169476
2 s1 a1 1.0644877
3 s1 a1 0.2007733
4 s1 b 0.8613291
5 s1 b -0.3682463
6 s2 g 1.2535321
7 s2 g 0.7622614
8 s2 g 1.4022664
9 s2 g1 -0.8234464
10 s2 g2 -1.0000354
11 s3 t 1.34320583
12 s3 t 1.33950010
13 s3 t -1.12670074
14 s3 t 1.59890652
15 s3 t 0.23932814
感谢您的帮助。
#old repex data from original question that has been edited above
library(tidyverse)
#create example dfs
df1 = data.frame(site = c(rep("s1",5), rep("s2",5)),grp = c("a1","a.","a.",rep("b",4),"b2","b-","bq"), measure = rnorm(10))
df2 = data.frame(site = c(rep("s1",10), rep("s2",16)), grp = c(rep("as", 3), "b2",rep("a",22)), measure2 = rnorm(26))
df3 = data.frame(site = c(rep("s1",3), rep("s2",6)),grp = c(rep("b-",3),rep("bq",2),"a", rep("a.", 3)), measure3 = 1:9)
site_list = list("s1","s2")
bad_values = list(c("a1","a.","as", "b2", "b-", "bq"),
c("a1","a.","as","b", "b2", "b-", "bq"))
good_values = list(c("a", "a1","a2","b","b1","b2"),
c("f","f1","f2","g","g","g1","g2"))
【问题讨论】: