检查行的NA,但是在单独的列中由值指定的起始列

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

我在R中有一个表,如下所示:

ID    Year    Source_1999    Source_2000    Source_2001    Source_2002
 1    1999            ABC            ABC           ABC             ABC
 2    2001            ABC            BBB           XYZ              NA
 3    2000             NA            ABC           BBB             BBB
 4    2001             NA             NA            NA              NA

该表有很多行,而且有很多“Source_”列 - 可能大约有50行。

我需要创建一个新列,说明任何源列是否包含NA,但我只想检查“年”列中年份大于或等于的年份。所以我的新表看起来像这样:

ID    Year    Source_1999    Source_2000    Source_2001    Source_2002   NA_check
 1    1999            ABC            ABC           ABC             ABC   No  
 2    2001            ABC            BBB           XYZ              NA  Yes 
 3    2000             NA            ABC           BBB             BBB   No
 4    2001             NA             NA            NA              NA  Yes

(新“NA”列中的值可以是任何类型的二进制指示符)

我已经尝试了每年轮流,并使用if循环功能is.na(df [,start_year:finish_year]),但这似乎不起作用,并且效率不高。

在将来,我可能想以这种方式检查其他列,即计算特定值,或者对行进行求和,但是使用本年份列指定的起始列,所以我希望我可以调整任何答案来执行此操作。

任何帮助非常感谢。谢谢

r dataframe dplyr data.table
3个回答
2
投票

gatherspreadtidyrgroup_by以及来自mutatedplyr和来自parse_numberreadrlibrary(tidyverse) mydata %>% gather(source, value, starts_with("Source")) %>% mutate(source_year = parse_number(source)) %>% group_by(ID, Year) %>% mutate(any_na = anyNA(value[Year <= source_year])) %>% select(-source_year) %>% spread(source, value) # A tibble: 4 x 7 # Groups: ID, Year [4] # ID Year any_na Source_1999 Source_2000 Source_2001 Source_2002 # <int> <int> <lgl> <chr> <chr> <chr> <chr> # 1 1 1999 FALSE ABC ABC ABC ABC # 2 2 2001 TRUE ABC BBB XYZ NA # 3 3 2000 FALSE NA ABC BBB BBB # 4 4 2001 TRUE NA NA NA NA 这是一个很好的任务:

mydata <- mydata %>% 
  gather(source, value, starts_with("Source")) %>% 
  mutate(source_year = parse_number(source)) 

mydata
# A tibble: 16 x 5
#      ID  Year source      value source_year
#   <int> <int> <chr>       <chr>       <dbl>
# 1     1  1999 Source_1999 ABC          1999
# 2     2  2001 Source_1999 ABC          1999
# 3     3  2000 Source_1999 NA           1999
# 4     4  2001 Source_1999 NA           1999
# 5     1  1999 Source_2000 ABC          2000
# ...

一步步 首先将数据从宽格式转换为长格式并提取源列的年份。

NA

然后按ID和年份分组,以便在这些组中应用以下计算。通过大于或等于组年份的source_Years过滤值,并检查是否有任何mydata <- mydata %>% group_by(ID, Year) %>% mutate(any_na = anyNA(value[Year <= source_year])) mydata # A tibble: 16 x 6 # Groups: ID, Year [4] # ID Year source value source_year any_na # <int> <int> <chr> <chr> <dbl> <lgl> # 1 1 1999 Source_1999 ABC 1999 FALSE # 2 2 2001 Source_1999 ABC 1999 TRUE # 3 3 2000 Source_1999 NA 1999 FALSE # 4 4 2001 Source_1999 NA 1999 TRUE # 5 1 1999 Source_2000 ABC 2000 FALSE # ...

mydata <- mydata %>% 
  select(-source_year) %>% 
  spread(source, value)

最后删除yource_year列,因为它不再需要了,并将数据从长格式转换为宽格式:

mydata <- tibble(ID = 1:4, 
                 Year = c(1999L, 2001L, 2000L, 2001L), 
                 Source_1999 = c("ABC", "ABC", NA, NA), 
                 Source_2000 = c("ABC", "BBB", "ABC", NA), 
                 Source_2001 = c("ABC", "XYZ", "BBB", NA), 
                 Source_2002 = c("ABC", NA, "BBB", NA))

数据

data.table

1
投票

这是两个dt[, NA_check := Reduce(`|`, lapply(paste0("Source_", 1999:2002), function(x) x >= paste0("Source_", Year) & is.na(get(x))))] 方法:

不一定最快:

checkNA <- melt(dt, id.vars=c("ID", "Year"), variable.factor=FALSE)[,
    anyNA(value[variable >= paste0("Source_", Year)]),
    by=.(ID, Year)]
dt[checkNA , on=.(ID, Year), NA_check := V1]

转换为长格式:

library(data.table)
dt <- fread("ID    Year    Source_1999    Source_2000    Source_2001    Source_2002
1    1999            ABC            ABC           ABC             ABC
2    2001            ABC            BBB           XYZ              NA
3    2000             NA            ABC           BBB             BBB
4    2001             NA             NA            NA              NA")

数据:

base R

0
投票

这是一个apply选项与anyNA,循环遍历行,获取第一个非NA元素的索引,从该元素子集行元素,检查NA与df1$any_NA <- apply(df1[-(1:2)], 1, function(x) c("No", "Yes")[anyNA(x[pmax(which(!is.na(x))[1], 1, na.rm = TRUE):length(x)]) + 1]) df1$any_NA #[1] "No" "Yes" "No" "Yes" 并创建基于此的'否/是'值

df1 <- structure(list(ID = 1:4, Year = c(1999L, 2001L, 2000L, 2001L), 
Source_1999 = c("ABC", "ABC", NA, NA), Source_2000 = c("ABC", 
"BBB", "ABC", NA), Source_2001 = c("ABC", "XYZ", "BBB", NA
), Source_2002 = c("ABC", NA, "BBB", NA)), class = "data.frame", row.names = c(NA, 
-4L))

data

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.