将逻辑下标与索引输入的大小相匹配

Matching logical subscripts to the size of the indexed input

我创建了两个数据框,然后将其转换为列表(例如,list1list2)。我从 list2 中删除了一个元素以更好地表示我的示例数据集。

library(dplyr)

intervals <- rep_len(c("01-01-2022", "01-11-2022", "01-31-2022"), 100)
ID <- rep(c("A","B", "C"), 100)
df <- data.frame(ID = as.factor(ID),
                 intervals = as.factor(intervals))

list1 <- df %>% 
  group_by(ID, intervals) %>% 
  group_split()

intervals <- rep_len(c("01-01-2022", "01-11-2022", "01-31-2022"), 25)
ID <- rep(c("A","B"), 25)
df2 <- data.frame(ID = as.factor(ID),
                 intervals = as.factor(intervals))

list2 <- df2 %>% 
  group_by(ID, intervals) %>% 
  group_split()

list2 <- list2[-6]

对于这些列表中的每一个,我都添加了一个属性,并且包含了一个函数来更容易地检查添加的属性 (check)。

# Convenience function to grab the attributes for you
check <- function(list, attribute_name) {
  return(attr(list, attribute_name))
}

# Add an attribute to hold the attributes of each list element
attr(list1, "match") <- data.frame(id = sapply(list1, function(x) paste(x$ID[1])),
                                  interval_start_date = sapply(list1, function(x) paste(x$intervals[1]))
)

# Check the attributes
check(list1, "match")

# Add an attribute "tab" to hold the attributes of each list element
attr(list2, "match") <- data.frame(id = sapply(list2, function(x) paste(x$ID[1])),
                                  interval_start_date = sapply(list2, function(x) paste(x$intervals[1]))
) 

# Check the attributes
check(list2, "match")

我已经为这两个列表创建了一个索引,这里的objective是删除任何不具有相同ID和相同intervals的列表组件。目标是只有匹配的 IDs 具有相同的 intervals.

# Creates an index for the two list based on the attributes, 
dat2 <- check(list1, "match")
dat1 <- check(list2, "match")

# Removes rows where the id isn't present in both data frames, and creates a 
# index where both the interval and id are the same.
if (!length(unique(dat2$id)) == length(unique(dat1$id))){
  dat3 <- dat2[dat2$id %in% dat1$id, ]
  dat4 <- dat1[dat1$id %in% dat2$id, ]
  
  i1 <-   paste(dat3[["id"]], format(as.Date(dat3[["interval_"]]),
                                     "%Y-%d")) %in%  
    paste(dat4[["id"]], format(as.Date(dat4[["interval_"]]), 
                               "%Y-%d"))
}

现在这里是我开始出现错误的地方:

# Error occurs because the lengths of `i1` is not the same as `list2`
out <- list1[i1]

我知道这是因为 list1 的长度与 i1 不同。我想知道是否有一种方法可以将逻辑值附加到 i1 以使其长度与 list1 相同,但不会从 list1 中删除值我们实际上确实想保留。有什么想法吗?

这是我对 list1 的预期输出,我希望它最终只有与 list2.[=34= 相同的 IDs 和 intervals ]

# Expected output
expected_list1 <- list(list1[1], list1[2],list1[3], list1[4], list1[5])

这个答案接近我想要的,但它有一个额外的元素。我认为最终属性 table 应该类似于 dat4.

 test <- list1[dat2$id %in% dat1$id][i1]
 # Add an attribute "tab" to hold the attributes of each list element
 attr(test, "match") <- data.frame(id = sapply(test, function(x) paste(x$ID[1])),
                                    interval_start_date = sapply(test, function(x) paste(x$intervals[1]))
 ) 
 
 # Check the attributes
 check(test, "match")

列名称不匹配,即它不是 interval_,而是 dat1dat2 中的 interval_start_date[[ 将查找完全匹配,而 $ 也可以匹配部分名称


if (!length(unique(dat2$id)) == length(unique(dat1$id))){
 ids_common <- intersect(dat2$id, dat1$id)
 inds1 <- dat2$id %in% ids_common
 inds2 <- dat1$id %in% ids_common
 i1 <-   paste(dat2[["id"]], format(as.Date(dat2[["interval_start_date"]]),
                                    "%Y-%d")) %in%  
   paste(dat1[["id"]], format(as.Date(dat1[["interval_start_date"]]), 
                              "%Y-%d"))
 
  out <- list1[i1 & inds1]
  
 
}

-正在检查

> length(out)
[1] 5
> i1
[1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE