编辑:我对原始表达的repex稍作更改,因为它没有产生与我的实际用法类似的示例。
这是上一个问题recode/replace multiple values in a shared data column to a single value across data frames的扩展,它对更简单的应用程序非常有用。我尝试无济于事,将解决方案扩展到稍微更复杂的情况。
我有许多不同的数据框,所有数据框都有一些共享的列(下面的repex中的“ site”和“ grp”)。在每个数据帧中,'grp'变量中存在多个错误,有些错误没有共享。在上一个问题中,使用tidyverse
和recode
函数来解决此问题,方法是创建一个{/ {1}}键/值元素,并使用
list
但是,当键/值列表取决于另一个共享变量“ site”的值时,我想这样做。例如,当site = s1时应将grp = a1重新编码为grp = a,而当site = s2时应重新编码为grp = f。在下面的示例中,我尝试使用keyval <- setNames(rep(good_values, lengths(bad_values)), unlist(bad_values))
out <- map(df_list, ~ .x %>%
mutate(grp = recode_factor(grp, !!! keyval)))
并嵌套调用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))))
这不会引发错误,但是也不能完全实现我想要的功能。它有一些不良的副作用:1)创建3个数据帧的3个列表,为每个键/值列表重新编码df,2)将因子“ 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)))
})
的意图,并不愿意使用它。因此,欢迎使用其他任何迭代方式完成此操作的方法。
我想期望的输出可能是map*()
与df_list相同的长度(本例中为3)。应该根据列表元素位置和“站点”将“ grp”变量=“ 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
中的第一个数据帧应类似于:
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
答案 0 :(得分:0)
我找到了一种完成此任务的方法,通过几个for循环和对上一个(链接的)问题的回答,可以很快地完成工作。如此简单,尴尬花了我这么长时间。
library(tidyverse)
keys = map2(good_values, bad_values, ~setNames(as.list(..1),unlist(..2)))
# how to accomplish
for(i in 1:length(site_list)){
for(df in 1:length(df_list)){
df_list[[df]] <- pluck(df_list, df) %>%
mutate(grp = if_else(site == pluck(site_list,i), recode(grp, !!!pluck(keys,i)),grp))
}
}
df_list[[1]]
site grp measure
1 s1 a 0.60083152
2 s1 a1 -0.56181835
3 s1 a1 1.31789556
4 s1 b -2.06659322
5 s1 b 1.21575623
6 s2 g -1.05263188
7 s2 g 1.68731655
8 s2 g -0.59827489
9 s2 g1 -2.22322604
10 s2 g2 0.22577945
11 s3 t -0.08614122
12 s3 t 0.74511934
13 s3 t 1.29782596
14 s3 t -1.87684060
15 s3 t -0.90672568