我在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, BUT 我只想检查大于或等于“年份”列中年份的年份。 。因此,我的新表将如下所示:
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”列中的值可以是任何一种二进制指示器)
我尝试每年轮流使用功能为is.na(df [,start_year:finish_year])的if循环,但这似乎行不通,而且效率不高。
将来,我可能希望以这种方式检查其他列,即计算特定值或对行求和,但要使用Year列指定的起始列,因此希望我可以调整所有答案以实现此目的。 / p>
任何帮助,不胜感激。谢谢
答案 0 :(得分:2)
对于gather
中的spread
和tidyr
以及group_by
和mutate
的{{1}},dplyr
来说,这是一个不错的任务来自parse_number
:
readr
分步
首先,将您的数据从宽格式转换为长格式,然后提取源列的年份。
library(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
然后按ID和年份分组,以便在这些组中应用以下计算。按source_Years大于或等于组年份的值过滤值,并检查是否有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
最后删除yource_year列,因为它不再需要了,并将数据从长格式转换为宽格式:
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)
答案 1 :(得分:1)
有两种data.table
方法:
不一定最快:
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")
答案 2 :(得分:0)
这里是base R
的{{1}}选项,用于遍历各行,获取第一个非NA元素的索引,将该元素的行元素子集化,并用{{1 }},并根据此值创建“否/是”值
apply
anyNA