简体   繁体   English

创建仅存储最后一个非 NA 值的最后一个非 NA 值表

[英]creating a table of last non-NA values that only stores last non-NA values

i am having trouble extracting some information from some data i'm working with.我无法从我正在使用的一些数据中提取一些信息。 i want to extract the last non-NA values for each id in each year and collect these results in a table which links those values with their original id and year values.我想提取year每个id的最后一个非 NA 值,并将这些结果收集在一个表中,该表将这些值与其原始idyear值链接起来。

here is what my data looks like.这是我的数据的样子。

dat <- data.frame(id = c(rep('a', 5), rep('b', 5), rep('c', 5)),
+                   year = c(seq(2011, 2015), seq(2011, 2015), seq(2011, 2015)),
+                   x = c(c(1:3, NA, NA), c(1:5), rep(NA, 5)),
+                   y = c(c(NA, NA, 3, 4, NA), c(NA, 2, 3, 4, NA), rep(NA, 5)),
+                   z = c(c(1:5), c(1:4, NA), rep(NA, 5)))
> 
> dat
   id year  x  y  z
1   a 2011  1 NA  1
2   a 2012  2 NA  2
3   a 2013  3  3  3
4   a 2014 NA  4  4
5   a 2015 NA NA  5
6   b 2011  1 NA  1
7   b 2012  2  2  2
8   b 2013  3  3  3
9   b 2014  4  4  4
10  b 2015  5 NA NA
11  c 2011 NA NA NA
12  c 2012 NA NA NA
13  c 2013 NA NA NA
14  c 2014 NA NA NA
15  c 2015 NA NA NA

here is what my ideal result looks like.这是我理想的结果。 i did this by hand.我是手工做的。 if an id / year pair has a non-NA value for x , y or z but that is not the last value by year, then i want it to be NA.如果id / year对具有xyz的非 NA 值,但这不是年份的最后一个值,那么我希望它是 NA。

for example, a has non-NA values for z in all years, so its last z value is 5 and in column z of the result table, i want NA for all years except that year for a .例如, a在所有年份中z的值都不是 NA ,所以它的最后一个z值是5并且在结果表的z列中,我想要除a那一年之外的所有年份的 NA 。

> target_result <- data.frame(id = c(rep('a', 3), rep('b', 3)),
+                            year = c(2013, 2014, 2015, 2015, 2014, 2014),
+                            last_x = c(3, NA, NA, 5, NA, NA),
+                            last_y = c(NA, 4, NA, NA, 4, NA),
+                            last_z = c(NA, NA, 5, NA, NA, 4))
> 
> target_result
  id year last_x last_y last_z
1  a 2013      3     NA     NA
2  a 2014     NA      4     NA
3  a 2015     NA     NA      5
4  b 2015      5     NA     NA
5  b 2014     NA      4     NA
6  b 2014     NA     NA      4

this is my analytical process so far.这是我到目前为止的分析过程。 i think my first step seems okay.我认为我的第一步似乎还可以。 i should clarify that the real data i'm working with has daily frequency.我应该澄清我正在使用的真实数据每天都有频率。 i kept my example data small for the sake of simplicity.为了简单起见,我将示例数据保持在较小的范围内。

> step_1 <- dat %>%
+   group_by(id, year) %>%
+   summarize(last_x = last(x),
+             last_y = last(y),
+             last_z = last(z))
`summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
> 
> step_1
# A tibble: 15 x 5
# Groups:   id [3]
   id     year last_x last_y last_z
   <chr> <int>  <int>  <dbl>  <int>
 1 a      2011      1     NA      1
 2 a      2012      2     NA      2
 3 a      2013      3      3      3
 4 a      2014     NA      4      4
 5 a      2015     NA     NA      5
 6 b      2011      1     NA      1
 7 b      2012      2      2      2
 8 b      2013      3      3      3
 9 b      2014      4      4      4
10 b      2015      5     NA     NA
11 c      2011     NA     NA     NA
12 c      2012     NA     NA     NA
13 c      2013     NA     NA     NA
14 c      2014     NA     NA     NA
15 c      2015     NA     NA     NA

second step also seems okay.第二步似乎还可以。 some of the rows from my ideal result are in here.我的理想结果中的一些行在这里。

> step_2 <- step_1[rowSums(is.na(step_1[,3:5])) < 3,]
> step_2
# A tibble: 10 x 5
# Groups:   id [2]
   id     year last_x last_y last_z
   <chr> <int>  <int>  <dbl>  <int>
 1 a      2011      1     NA      1
 2 a      2012      2     NA      2
 3 a      2013      3      3      3
 4 a      2014     NA      4      4
 5 a      2015     NA     NA      5
 6 b      2011      1     NA      1
 7 b      2012      2      2      2
 8 b      2013      3      3      3
 9 b      2014      4      4      4
10 b      2015      5     NA     NA

but i know that my third step is wrong because it destroys the relationship between the last_ columns and year and just collapses everything into a table that doesn't contain any NA values.但我知道我的第三步是错误的,因为它破坏了last_列和year之间的关系,并且只是将所有内容折叠到一个不包含任何 NA 值的表中。

> small_and_wrong <- as.data.frame(as.data.table(step_2)[, lapply(.SD, function(x) last(na.omit(x))), id])
> small_and_wrong
  id year last_x last_y last_z
1  a 2015      3      4      5
2  b 2015      5      4      4

any advice for how to get back on track?关于如何重回正轨的任何建议? thank you in advance.先感谢您。

maybe such a solution will be useful也许这样的解决方案会很有用

tidyverse tidyverse

df <- data.frame(
  id = c(rep('a', 5), rep('b', 5), rep('c', 5)),
  year = c(seq(2011, 2015), seq(2011, 2015), seq(2011, 2015)),
  x = c(c(1:3, NA, NA), c(1:5), rep(NA, 5)),
  y = c(c(NA, NA, 3, 4, NA), c(NA, 2, 3, 4, NA), rep(NA, 5)),
  z = c(c(1:5), c(1:4, NA), rep(NA, 5))
)

library(tidyverse)
df %>% 
  pivot_longer(-c(id, year), values_drop_na = TRUE) %>% 
  group_by(id, name) %>% 
  slice_tail(n = 1) %>% 
  ungroup() %>% 
  pivot_wider(id_cols = c(id, year), names_from = name, values_from = value)
#> # A tibble: 5 x 5
#>   id     year     x     y     z
#>   <chr> <int> <dbl> <dbl> <dbl>
#> 1 a      2013     3    NA    NA
#> 2 a      2014    NA     4    NA
#> 3 a      2015    NA    NA     5
#> 4 b      2015     5    NA    NA
#> 5 b      2014    NA     4     4

Created on 2021-11-24 by the reprex package (v2.0.1)代表 package (v2.0.1) 于 2021 年 11 月 24 日创建

data.table data.table


library(data.table)
library(magrittr)

melt(data = setDT(df), id.vars = c("id", "year"), na.rm = TRUE) %>% 
  .[order(id, year), last(.SD), by = list(id, variable)] %>% 
  dcast(formula = id + year ~ variable)

#>    id year  x  y  z
#> 1:  a 2013  3 NA NA
#> 2:  a 2014 NA  4 NA
#> 3:  a 2015 NA NA  5
#> 4:  b 2014 NA  4  4
#> 5:  b 2015  5 NA NA

Created on 2021-11-24 by the reprex package (v2.0.1)代表 package (v2.0.1) 于 2021 年 11 月 24 日创建

Perhaps this helps也许这有帮助

library(dplyr)
dat %>% 
   group_by(id) %>% 
   mutate(across(x:z, ~ replace(.x, 
      row_number() < if(any(!is.na(.x))) max(which(!is.na(.x))) 
         else n(), NA))) %>% 
   ungroup %>%
   filter(if_any(x:z, ~ !is.na(.x)))

By considering max values for non NA values for each column and then applying a condition between year and newly created max column values.通过考虑每列的非 NA 值的最大值,然后在年份和新创建的最大列值之间应用条件。

dat <- data.frame(id = c(rep('a', 5), rep('b', 5), rep('c', 5)), 
                  year = c(seq(2011, 2015), seq(2011, 2015), seq(2011, 2015)), 
                  x = c(c(1:3, NA, NA), c(1:5), rep(NA, 5)), 
                  y = c(c(NA, NA, 3, 4, NA), c(NA, 2, 3, 4, NA), rep(NA, 5)), 
                  z = c(c(1:5), c(1:4, NA), rep(NA, 5)))

library(data.table)

setDT(dat)

Creating columns which contains the max year for non NA values based on each column x, y and z grouped by id根据按 id 分组的每列 x、y 和 z 创建包含非 NA 值的最大年份的列

dat[!is.na(x),':='(Max_YearX = max(year)), by = .(id)]
dat[!is.na(y),':='(Max_YearY = max(year)), by = .(id)]
dat[!is.na(z),':='(Max_YearZ = max(year)), by = .(id)]

Changing all the values to NA wherever year is not same.在年份不同的地方将所有值更改为 NA。

dat[,':='(x = ifelse(Max_YearX != year, NA, x), 
          y = ifelse(Max_YearY != year, NA, y), 
          z = ifelse(Max_YearZ != year, NA, z))]

Keeping only the required columns仅保留所需的列

dat <- dat[,.(id, year, x, y, z)]

dat

    id year  x  y  z
 1:  a 2011 NA NA NA
 2:  a 2012 NA NA NA
 3:  a 2013  3 NA NA
 4:  a 2014 NA  4 NA
 5:  a 2015 NA NA  5
 6:  b 2011 NA NA NA
 7:  b 2012 NA NA NA
 8:  b 2013 NA NA NA
 9:  b 2014 NA  4  4
10:  b 2015  5 NA NA
11:  c 2011 NA NA NA
12:  c 2012 NA NA NA
13:  c 2013 NA NA NA
14:  c 2014 NA NA NA
15:  c 2015 NA NA NA

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM