【问题标题】:R coalesce down columns by identifer [duplicate]R按标识符合并列[重复]
【发布时间】:2020-06-24 00:24:23
【问题描述】:

我有一个很长的数据集,其中包含跨多个学期的学生成绩和课程。每个学生都有许多 NA 和许多行。我希望每个学生有一个长行来填写这些 NA,但保持相同的列名。

这是一个示例:

library(tidyverse)
sample <- tibble(student = c("Corey", "Corey", "Sibley", "Sibley"),
                 fall_course_1 = c("Math", NA, "Science", NA),
                 fall_course_2 = c(NA, "English", NA, NA),
                 fall_grade_1 = c(90, NA, 98, NA),
                 fall_grade_2 = c(NA, 60, NA, NA))

这是我想要的样子:

library(tidyverse)
answer <- tibble(student = c("Corey", "Sibley"),
                 fall_course_1 = c("Math", "Science"),
                 fall_course_2 = c("English", NA),
                 fall_grade_1 = c(90, 98),
                 fall_grade_2 = c(60, NA))

有些学期,有些学生上很多课,有些只上一门。我尝试过使用 coalesce(),但我无法弄清楚。任何帮助将不胜感激!

【问题讨论】:

  • 你试过什么没用?
  • @camille,我尝试按学生列分组并使用 coalesce()。然后我尝试了这个链接上的建议,但它跨越了列,而不是向下:community.rstudio.com/t/…
  • 与其继续斗争,不如将数据集重塑为长格式,每个等级都是一行。这将使这些扭曲变得不必要。见stackoverflow.com/questions/2185252/…
  • 我应该更具体一些。将您的代码尝试添加到问题中,这样人们就可以看到您正在使用的逻辑而不是建议您已经尝试过的事情

标签: r reshape tidyr data-cleaning coalesce


【解决方案1】:

应该这样做,将数据旋转长,删除 na,然后将其旋转回宽。

您需要将数值暂时转换为字符,以便它们可以与课程标签在同一列中,然后 type_convert() 是一种懒惰的方式将它们重新放回去。

library(dplyr)
library(tidyr)
library(readr)

reshaped <- sample %>%
  mutate_if(is.numeric, as.character) %>%
  pivot_longer(-student) %>% 
  drop_na() %>% 
  pivot_wider(student, names_from = name, values_from = value) %>% 
  type_convert()

【讨论】:

    【解决方案2】:

    你也可以如下使用data.table包:

    library(data.table)
    setDT(sample)[, lapply(.SD, na.omit), student]
    
    sample
    # 1:   Corey          Math       English           90           60
    # 2:  Sibley       Science          <NA>           98           NA
    

    【讨论】:

      【解决方案3】:

      对于每个 student,您可以获得每列中的第一个非 NA 值。

      library(dplyr)
      sample %> group_by(student) %>% summarise_all(~na.omit(.)[1])
      
      # A tibble: 2 x 5
      #  student fall_course_1 fall_course_2 fall_grade_1 fall_grade_2
      #  <chr>   <chr>         <chr>                <dbl>        <dbl>
      #1 Corey   Math          English                 90           60
      #2 Sibley  Science       NA                      98           NA
      

      如果组中有所有NA 值,则此方法返回NA

      【讨论】:

      • 这太好了,谢谢!快速跟进,您能解释一下代码的 summarise_all(~na.omit(.)[1]) 方面吗?我可以确认它有效,但我很想知道如何阅读它。谢谢!
      • @J.Sabree 顾名思义,na.omit 删除所有 NA 值,我们在使用索引 [1] 删除 NA 后选择第一个值。当数据中包含所有 NA 值时,它默认返回 NAna.omit(c(NA, NA, NA))[1]
      【解决方案4】:

      使用自定义的 colaesce 函数和 dplyr:

      coalesce_all_columns <- function(df) {
        return(coalesce(!!! as.list(df)))
      }
      
      library(dplyr)
      
      sample %>%
        group_by(student) %>%
        summarise_all(coalesce_all_columns)
      

      # A tibble: 2 x 5
        student fall_course_1 fall_course_2 fall_grade_1 fall_grade_2
        <chr>   <chr>         <chr>                <dbl>        <dbl>
      1 Corey   Math          English                 90           60
      2 Sibley  Science       NA                      98           NA
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-18
        • 1970-01-01
        • 2018-11-02
        相关资源
        最近更新 更多