dplyr按变量等级折叠,但忽略NA

时间:2018-08-15 07:05:15

标签: r dplyr summarize

我正在努力解决数据崩溃的问题。

基本上,我的数据由多个指标组成,并且每年都有多个观测值。我想将其转换为每个国家/地区每个指标的一项观察结果。

我有一个等级指示器,它指定必须选择观察序列的序列。

基本上,必须选择具有第一个等级的观察值(因此用1代替2),只要该等级的值不是NA。

另一个问题:我的数据集中的年份会随时间而变化,因此有一种方法可以使代码具有动态性,即它将代码应用于1990年到2025年之间的所有列名(如果存在)?

df <- data.frame(country.code = c(1,1,1,1,1,1,1,1,1,1,1,1), 
                        id = as.factor(c("GDP", "GDP", "GDP", "GDP", "CA", "CA", "CA", "GR", "GR", "GR", "GR", "GR")), 
                       `1999` = c(NA,NA,NA, 1000,NA,NA, 100,NA,NA, NA,NA,22), 
                       `2000` = c(NA,NA,1, 2,NA,1, 2,NA,1000, 12,13,2), 
                       `2001` = c(3,100,1, 3,100,20, 1,1,44, 65,NA,NA),
                       rank = c(1, 2 , 3 , 4 , 1, 2, 3, 1, 3, 2, 4, 5))

结果应为以下数据集:

    result <- data.frame(country.code = c(1, 1, 1), 
                         id = as.factor(c("GDP", "CA", "GR")),
                         `1999`= c(1000, 100, 22),
                         `2000`= c(1, 1, 12),
                         `2001`= c(3, 100, 1))

我尝试了以下解决方案(但鉴于数据中不存在NA,因此该方法不起作用,我必须指定每列:

    test <- df %>% group_by(Country.Code, Indicator.Code) %>% 
                summarise(test1999 = `1999`[which.min(rank))

我看不到如何解释R来省略1999列中NA的情况。

3 个答案:

答案 0 :(得分:4)

我们可以为列x[rank==min(rank[!is.na(x)])]使用非空值的最小秩进行子集。

  

另一个问题:我的数据集中的年份随时间而变化,....

使用summarise_atvarsmatches可以使用正则表达式[0-9]{4}来选择任何4位数字的列名,即1990-2025(这意味着搜索一个数字“ 0-9”精确地重复了4次),然后使用funs

对他们应用上述过程
librar(dplyr)    
df %>% group_by(country.code,id) %>% 
       summarise(`1999` = `1999`[rank==ifelse(all(is.na(`1999`)),1, min(rank[!is.na(`1999`)]))])

df %>% group_by(country.code,id) %>% 
       summarise_at(vars(matches("[0-9]{4}")),funs(.[rank==ifelse(all(is.na(.)), 1, min(rank[!is.na(.)]))]))

 # A tibble: 3 x 5
 # Groups:   country.code [?]
  country.code id    `1999` `2000` `2001`
         <dbl> <fct>  <dbl>  <dbl>  <dbl>
1            1 CA       100      1    100
2            1 GDP     1000      1      3
3            1 GR        22     12      1

答案 1 :(得分:0)

这是一个选项,在我们将数据tidyr::fill NA NA替换为arrange后,用第一个非id值替换rankgather。这可能不是最有效的方法,因为我们首先spread,然后再次library(tidyverse) df %>% arrange(id, rank) %>% gather(key, value, X1999:X2001) %>% tidyr::fill(value, .direction = "up") %>% spread(key, value) %>% group_by(id) %>% slice(1) %>% ungroup() # A tibble: 3 x 6 # country.code id rank X1999 X2000 X2001 # <dbl> <fct> <dbl> <dbl> <dbl> <dbl> #1 1 CA 1 100 1 100 #2 1 GDP 1 1000 1 3 #3 1 GR 1 22 12 1 数据。

1999

注意:列名可能不像您的数据中的2000pipeline { agent any stages { stage ('work') { input { message 'message' parameters { text( name: 'values', ) } } steps { script { env.values = values } sh """#!/bin/bash -xe echo $values """ } } } } 等。但这很容易采用。

答案 2 :(得分:0)

您可以将数据框更改为长格式,删除na,选择与最小排名相对应的值,然后再扩展回宽格式

 library(tidyr)
  test <- df %>%
  gather("Year", "Value", X1999:X2001) %>%
  filter(!is.na(Value))%>%
  group_by(country.code, id, Year) %>% 
  arrange(rank)%>%
  summarise(first(Value)) %>%
  spread(Year, `first(Value)`)