基于参考数据帧,有条件地从另一个数据帧列表中替换数据帧列表中的值

问题描述 投票:0回答:1

我有两个数据框列表,

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)
r dataframe list
1个回答
1
投票

这是嵌套列表/框架的“开始”。

首先,为了方便起见,我将

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
© www.soinside.com 2019 - 2024. All rights reserved.