我有两个数据框列表,
main_list
和 outside_list
。这些列表中的每个数据框都包含列 idvar
(字符标识符)和 col1
、col2
和 col3
(所有数字)。我也有参考数据框(ref
),它指示特定级别idvar
的特定列是“好”还是“坏”。
我想将
main_list
的值替换为 outside_list
的值,但仅适用于“坏”的 idvar
级别的特定列。例如,如果 ref
说 idvar col1
的 001
是“坏的”,那么我想用 main_list
中包含的值替换 outside_list
中的那个值。如果 ref
说 col2
的 003
是“好”,那么我不想对 main_list
中的那个值做任何事情。此外,idvar
中的outside_list
的每个级别可能会有一两行额外的行;如果是这种情况,我只想删除 idvar
中 outside_list
级别的该列的那些额外行。
set.seed(1234)
# my main list of dataframes
df1 <- data.frame(idvar = "001", col1 = as.numeric(sample(1:5, 10, replace = TRUE)), col2 = as.numeric(sample(1:5, 10, replace = TRUE)), col3 = as.numeric(sample(1:5, 10, replace = TRUE)))
df2 <- data.frame(idvar = "002", col1 = as.numeric(sample(1:5, 9, replace = TRUE)), col2 = as.numeric(sample(1:5, 9, replace = TRUE)), col3 = as.numeric(sample(1:5, 9, replace = TRUE)))
df3 <- data.frame(idvar = "003", col1 = as.numeric(sample(1:5, 12, replace = TRUE)), col2 = as.numeric(sample(1:5, 12, replace = TRUE)), col3 = as.numeric(sample(1:5, 12, replace = TRUE)))
df4 <- data.frame(idvar = "004", col1 = as.numeric(sample(1:5, 8, replace = TRUE)), col2 = as.numeric(sample(1:5, 8, replace = TRUE)), col3 = as.numeric(sample(1:5, 8, replace = TRUE)))
df5 <- data.frame(idvar = "005", col1 = as.numeric(sample(1:5, 11, replace = TRUE)), col2 = as.numeric(sample(1:5, 11, replace = TRUE)), col3 = as.numeric(sample(1:5, 11, replace = TRUE)))
main_list <- list(df1, df2, df3, df4, df5)
# my reference dataframe
ref <- structure(list(idvar = c("001", "002", "003", "004", "005"), col1 = c("BAD", "BAD", "GOOD", "BAD", "GOOD"), col2 = c("BAD", "BAD", "GOOD", "GOOD", "GOOD"), col3 = c("BAD", "BAD", "GOOD", "GOOD", "GOOD")), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"))
# my outside list of dataframes
df1 <- data.frame(idvar = "001", col1 = as.numeric(sample(1:5, 10, replace = TRUE)), col2 = as.numeric(sample(1:5, 10, replace = TRUE)), col3 = as.numeric(sample(1:5, 10, replace = TRUE)))
df2 <- data.frame(idvar = "002", col1 = as.numeric(sample(1:5, 10, replace = TRUE)), col2 = as.numeric(sample(1:5, 10, replace = TRUE)), col3 = as.numeric(sample(1:5, 10, replace = TRUE)))
df3 <- data.frame(idvar = "003", col1 = as.numeric(sample(1:5, 12, replace = TRUE)), col2 = as.numeric(sample(1:5, 12, replace = TRUE)), col3 = as.numeric(sample(1:5, 12, replace = TRUE)))
df4 <- data.frame(idvar = "004", col1 = as.numeric(sample(1:5, 9, replace = TRUE)), col2 = as.numeric(sample(1:5, 9, replace = TRUE)), col3 = as.numeric(sample(1:5, 9, replace = TRUE)))
df5 <- data.frame(idvar = "005", col1 = as.numeric(sample(1:5, 13, replace = TRUE)), col2 = as.numeric(sample(1:5, 13, replace = TRUE)), col3 = as.numeric(sample(1:5, 13, replace = TRUE)))
outside_list <- list(df1, df2, df3, df4, df5)
这是嵌套列表/框架的“开始”。
首先,为了方便起见,我将
ref
转换为大部分logical
:
ref[,-1] <- lapply(ref[,-1], `==`, "GOOD")
ref
# # A tibble: 5 × 4
# idvar col1 col2 col3
# <chr> <lgl> <lgl> <lgl>
# 1 001 FALSE FALSE FALSE
# 2 002 FALSE FALSE FALSE
# 3 003 TRUE TRUE TRUE
# 4 004 FALSE TRUE TRUE
# 5 005 TRUE TRUE TRUE
我们可以处理
outside_list
中的额外行,方法是用相应的 head
中的行数调用 main_list
:
Map(head, outside_list, sapply(main_list, nrow))
我们可以将
ref
中的逻辑列合并到 main_list
中,以便每个 idvar
的相应逻辑正确关联。
lapply(main_list, merge, ref, by = "idvar", suffix=c("", ".y"))
顶层
Map
的内部结构是迭代每个发现的列和ifelse
它们基于ref
的加入列。
Map(function(main, out) {
Ys <- grep("\\.y$", names(main), value=TRUE)
main[,sub("\\.y", "", Ys)] <-
Map(ifelse, main[,Ys], main[,sub("\\.y", "", Ys)], out[,sub("\\.y", "", Ys)])
main[,Ys] <- NULL
main
}, lapply(main_list, merge, ref, by = "idvar", suffix=c("", ".y")),
Map(head, outside_list, sapply(main_list, nrow)))
# [[1]]
# idvar col1 col2 col3
# 1 001 2 1 5
# 2 001 2 5 1
# 3 001 3 3 1
# 4 001 1 3 4
# 5 001 2 4 4
# 6 001 5 4 5
# 7 001 4 3 3
# 8 001 4 3 2
# 9 001 2 1 5
# 10 001 4 3 5
# [[2]]
# idvar col1 col2 col3
# 1 002 4 1 1
# 2 002 5 5 5
# 3 002 1 5 2
# 4 002 5 3 2
# 5 002 5 4 3
# 6 002 2 4 1
# 7 002 5 1 2
# 8 002 3 4 4
# 9 002 2 4 3
# [[3]]
# idvar col1 col2 col3
# 1 003 3 2 3
# 2 003 5 5 2
# 3 003 3 5 4
# 4 003 4 5 5
# 5 003 4 1 2
# 6 003 1 2 1
# 7 003 4 2 3
# 8 003 4 2 3
# 9 003 3 5 1
# 10 003 1 3 5
# 11 003 4 4 1
# 12 003 1 4 5
# [[4]]
# idvar col1 col2 col3
# 1 004 2 1 5
# 2 004 3 3 5
# 3 004 5 4 1
# 4 004 1 3 3
# 5 004 5 3 3
# 6 004 3 2 3
# 7 004 3 4 5
# 8 004 3 2 1
# [[5]]
# idvar col1 col2 col3
# 1 005 4 1 3
# 2 005 4 3 2
# 3 005 3 1 3
# 4 005 2 1 4
# 5 005 1 4 3
# 6 005 1 4 5
# 7 005 3 5 1
# 8 005 2 1 3
# 9 005 5 3 2
# 10 005 2 5 3
# 11 005 1 2 3