Reputation: 83
I would like to get the year of the latest available data for each combination of country(iso3), indicator(gho_id),gender(sex), type of residence(location). The data are stored in "gho_value". My dataset looks like that:
# A tibble: 16 x 6
iso3 gho_id sex location year gho_value
<chr> <chr> <chr> <chr> <dbl> <dbl>
1 AFG BP_04 FMLE <NA> 2000 28.6
2 AFG BP_04 FMLE <NA> 2001 28.8
3 AFG BP_04 FMLE <NA> 2002 29
4 AFG BP_04 FMLE <NA> 2003 29.2
5 AFG BP_04 FMLE <NA> 2004 29.4
6 AFG BP_04 FMLE <NA> 2005 29.5
7 AFG BP_04 FMLE <NA> 2006 29.7
8 AFG BP_04 FMLE <NA> 2007 29.8
9 AFG BP_04 FMLE <NA> 2008 29.9
10 AFG BP_04 FMLE <NA> 2009 30.1
11 AFG BP_04 FMLE <NA> 2010 30.2
12 AFG BP_04 FMLE <NA> 2011 30.3
13 AFG BP_04 FMLE <NA> 2012 30.4
14 AFG BP_04 FMLE <NA> 2013 30.5
15 AFG BP_04 FMLE <NA> 2014 NA
16 AFG BP_04 FMLE <NA> 2015 NA
I would like to have this:
# A tibble: 16 x 7
iso3 gho_id sex location year gho_value last_year
<chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 AFG BP_04 FMLE <NA> 2000 28.6 2013
2 AFG BP_04 FMLE <NA> 2001 28.8 2013
3 AFG BP_04 FMLE <NA> 2002 29 2013
4 AFG BP_04 FMLE <NA> 2003 29.2 2013
5 AFG BP_04 FMLE <NA> 2004 29.4 2013
6 AFG BP_04 FMLE <NA> 2005 29.5 2013
7 AFG BP_04 FMLE <NA> 2006 29.7 2013
8 AFG BP_04 FMLE <NA> 2007 29.8 2013
9 AFG BP_04 FMLE <NA> 2008 29.9 2013
10 AFG BP_04 FMLE <NA> 2009 30.1 2013
11 AFG BP_04 FMLE <NA> 2010 30.2 2013
12 AFG BP_04 FMLE <NA> 2011 30.3 2013
13 AFG BP_04 FMLE <NA> 2012 30.4 2013
14 AFG BP_04 FMLE <NA> 2013 30.5 2013
15 AFG BP_04 FMLE <NA> 2014 NA 2013
16 AFG BP_04 FMLE <NA> 2015 NA 2013
I have tried to use the tidyverse package (dpylr) and did this:
ungho2 <- left_join(ungho,
ungho %>%
arrange(iso3,gho_id,sex,location,year) %>%
group_by(iso3,gho_id,sex,location) %>%
filter(!(is.na(gho_value))) %>%
mutate(latest_year_gho = last(year)) %>%
ungroup(iso3,gho_id,sex,location))
My problem is that I get this (NA instead of 2013 when I use left_join):
# A tibble: 16 x 7
iso3 gho_id sex location year gho_value last_year
<chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 AFG BP_04 FMLE <NA> 2000 28.6 2013
2 AFG BP_04 FMLE <NA> 2001 28.8 2013
3 AFG BP_04 FMLE <NA> 2002 29 2013
4 AFG BP_04 FMLE <NA> 2003 29.2 2013
5 AFG BP_04 FMLE <NA> 2004 29.4 2013
6 AFG BP_04 FMLE <NA> 2005 29.5 2013
7 AFG BP_04 FMLE <NA> 2006 29.7 2013
8 AFG BP_04 FMLE <NA> 2007 29.8 2013
9 AFG BP_04 FMLE <NA> 2008 29.9 2013
10 AFG BP_04 FMLE <NA> 2009 30.1 2013
11 AFG BP_04 FMLE <NA> 2010 30.2 2013
12 AFG BP_04 FMLE <NA> 2011 30.3 2013
13 AFG BP_04 FMLE <NA> 2012 30.4 2013
14 AFG BP_04 FMLE <NA> 2013 30.5 2013
15 AFG BP_04 FMLE <NA> 2014 NA NA
16 AFG BP_04 FMLE <NA> 2015 NA NA
What could I do?
Thank you very much for your help!
Upvotes: 0
Views: 67
Reputation: 5798
Base R solution:
df <- data.frame(do.call("rbind", lapply(split(df, paste0(df$iso3, df$gho_id, df$sex, df$location)),
function(x){x$last_year <- max(x$year[!(is.na(x$gho_value))]); return(x)})), row.names = NULL)
Tidyverse solution (handling case when the entire series is NA):
require(dplyr)
df %>%
group_by(iso3, gho_id, sex, location) %>%
mutate(last_year = ifelse(all(is.na(gho_value)), NA, max(year[!is.na(gho_value)]))) %>%
ungroup()
Data:
df <- data.frame(iso3 = rep("AFG", 16),
gho_id = rep("BP04", 16),
sex = rep("FMLE", 16),
location = rep(NA, 16),
year = seq.int(2000, 2015),
gho_value = as.numeric(c(28.6, 28.8, 29, 29.2, 29.4, 29.5, 29.7, 29.8,
29.9, 30.1, 30.2, 30.3, 30.4, 30.5, NA, NA)))
Upvotes: 0
Reputation: 1488
Since you're already using dplyr
, here's a simple solution:
df <- data.frame(iso3 = rep("AFG", 16),
gho_id = rep("BP04", 16),
sex = rep("FMLE", 16),
location = rep(NA, 16),
year = seq.int(2000, 2015),
gho_value = as.numeric(c(28.6, 28.8, 29, 29.2, 29.4, 29.5, 29.7, 29.8,
29.9, 30.1, 30.2, 30.3, 30.4, 30.5, NA, NA)))
library(dplyr)
df %>%
# Group by the variables you wanted to
group_by(iso3, gho_id, sex, location) %>%
# Get the max year when `gho_value` is not NA for each group defined above
mutate(last_year = max(year[!is.na(gho_value)]))
Upvotes: 1
Reputation: 102920
With base R
, I guess the following code might help (assuming df
is data.frame
for your data)
df$last_year <- df$year[tail(which(rowSums(!is.na(df[-4]))==ncol(df[-1])),1)]
which gives
> df
iso3 gho_id sex location year gho_value last_year
1 AFG BP_04 FMLE <NA> 2000 28.6 2013
2 AFG BP_04 FMLE <NA> 2001 28.8 2013
3 AFG BP_04 FMLE <NA> 2002 29.0 2013
4 AFG BP_04 FMLE <NA> 2003 29.2 2013
5 AFG BP_04 FMLE <NA> 2004 29.4 2013
6 AFG BP_04 FMLE <NA> 2005 29.5 2013
7 AFG BP_04 FMLE <NA> 2006 29.7 2013
8 AFG BP_04 FMLE <NA> 2007 29.8 2013
9 AFG BP_04 FMLE <NA> 2008 29.9 2013
10 AFG BP_04 FMLE <NA> 2009 30.1 2013
11 AFG BP_04 FMLE <NA> 2010 30.2 2013
12 AFG BP_04 FMLE <NA> 2011 30.3 2013
13 AFG BP_04 FMLE <NA> 2012 30.4 2013
14 AFG BP_04 FMLE <NA> 2013 30.5 2013
15 AFG BP_04 FMLE <NA> 2014 NA 2013
16 AFG BP_04 FMLE <NA> 2015 NA 2013
DATA
df <- structure(list(iso3 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "AFG", class = "factor"),
gho_id = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "BP_04", class = "factor"),
sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L), .Label = "FMLE", class = "factor"),
location = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "<NA>", class = "factor"),
year = 2000:2015, gho_value = c(28.6, 28.8, 29, 29.2, 29.4,
29.5, 29.7, 29.8, 29.9, 30.1, 30.2, 30.3, 30.4, 30.5, NA,
NA)), row.names = c(NA, -16L), class = "data.frame")
Upvotes: 0