繁体   English   中英

如何根据特定条件删除行并连接两个数据框?

[英]How to remove rows and join two data frames based on certain conditions?

这是一组 2 个数据框。

id <- c(1,2,3,4)
id2 <- c(5,6,7,8)
list <- c("list1","list2","list3","list4")
progress <- c("A", "A", "B", "C")
grade <- c("A", NA, "B", "C")
df1 <- data.frame(id, id2, list, progress, grade)
df1

id <- c(1,2,3,5)
id2 <- c(5,6,7,9)
list <- c("list1","list2","list5","list6")
progress <- c("B", "B", "A", "D")
grade2 <- c("B", NA, "B", "D")
df2 <- data.frame(id, id2, list, progress, grade2)
df2

我希望以这样的方式组合df1df2

a) 对于列list ,如果idid2的值重复,则list对应的值也应该匹配。 否则该值应返回NA 此条件不适用于idid2的唯一值。

b) progress列如果idid2有重复的值,则取第一次出现的值。

c) 对于列gradegrade2 ,如果idid2的值重复,则在这种情况下必须删除NA

预期的 output 如下:-

   #id id2  list   progress grade grade2
   #1   5   list1        A     A   B
   #2   6   list2        A    NA   NA
   #3   7   NA           B     B   B
   #4   8   list4        C     C   NA
   #5   9   list6        D    NA   D

由于您的初始数据结构,这个答案相当复杂,但这是我使用dplyr中的工具的解决方案:

library(dplyr)
# Bind the rows of the two dataframes together
bind_rows(df1, df2) %>%
    # a) For each pair of id and id2...
    group_by(id, id2) %>% 
    # ...when there is more than one list, set to NA, otherwise, take the value
    mutate(list = case_when(length(unique(list)) > 1 ~ NA_character_, 
                            TRUE ~ unique(list))) %>% 
    # b) Take the first occurring progress value (still for each id, id2 pair)
    mutate(progress = progress[1]) %>% 
    ungroup() %>% 
    # Keep distinct pairs
    distinct(id, id2, list, progress) %>% 
    # c)
    # Create a smaller data set of the non-NA grade for the id, id2 pairs
    # Joint it onto the larger data set
    left_join(
        bind_rows(df1, df2) %>% 
        select(id, id2, grade) %>% 
        na.omit(),
        by = c("id", "id2")
    ) %>% 
    # c continued)
    # Create a smaller data set of the non-NA grade2 for the id, id2 pairs
    # Joint it onto the larger data set
    left_join(
        bind_rows(df1, df2) %>% 
        select(id, id2, grade2) %>% 
        na.omit(),
        by = c("id", "id2")
    )   

“第一”困扰着我,但这似乎符合您想要的 output:

library(tidyverse)

bind_rows(
  left_join(df1, df2, by = c('id', 'id2', 'list', 'progress'), ),
  anti_join(df2, df1, by = c('id', 'id2', 'list', 'progress'))
  ) %>%
  group_by(id, id2) %>%
  mutate(
    list     = ifelse(n_distinct(list) > 1, NA, list),
    progress = first(progress),
    grade    = first(grade),
    grade2   = first(na.omit(grade2))
  ) %>%
  ungroup() %>%
  distinct()

Output:

# # A tibble: 5 x 6
#      id   id2 list  progress grade grade2
#   <dbl> <dbl> <chr> <chr>    <chr> <chr> 
# 1     1     5 list1 A        A     B     
# 2     2     6 list2 A        NA    NA    
# 3     3     7 NA    B        B     B     
# 4     4     8 list4 C        C     NA    
# 5     5     9 list6 D        NA    D 

数据:

df1 <- data.frame(
  id       = 1:4,
  id2      = 5:8,
  list     = paste0('list', 1:4),
  progress = c('A', 'A', 'B', 'C'),
  grade    = c('A', NA, 'B', 'C'),
  stringsAsFactors = FALSE
)

df2 <- data.frame(
  id       = c(1, 2, 3, 5),
  id2      = c(5, 6, 7, 9),
  list     = paste0('list', c(1, 2, 5, 6)),
  progress = c('B', 'B', 'A', 'D'),
  grade2   = c('B', NA, 'B', 'D'),
  stringsAsFactors = FALSE
)

这是dplyrpurrr package 的另一种选择。

library(purrr)
library(dplyr)

x <- list(df1, df2) %>% reduce(full_join, by = c("id","id2"))

x$progress.x <- as.character(x$progress.x)    
x$progress.y <- as.character(x$progress.y)

coalesce_unless <- function(x, y){
    
    cxy <- coalesce(x, y)
    cyx <- coalesce(y, x)
    
    cxy[cxy != cyx] <- NA
    
    cxy
    
}

x %>% 
    mutate(list = coalesce_unless(list.x, list.y)) %>%
    mutate(progress = ifelse(is.na(x$progress.x), x$progress.y, x$progress.x))%>% 
    select(id, id2, list, progress, grade, grade2)

#   id id2 list progress grade grade2
#1  1   5 list1        A     A      B
#2  2   6 list2        A  <NA>   <NA>
#3  3   7  <NA>        B     B      B
#4  4   8 list4        C     C   <NA>
#5  5   9 list6        D  <NA>      D

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM