[英]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 值,并将这些结果收集在一个表中,该表将这些值与其原始id
和year
值链接起来。
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
对具有x
、 y
或z
的非 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.