创建仅存储最后一个非 NA 值的最后一个非 NA 值的 table
creating a table of last non-NA values that only stores last non-NA values
我无法从我正在处理的一些数据中提取一些信息。我想提取每个 year
中每个 id
的最后一个非 NA 值,并将这些结果收集在 table 中,它将这些值与它们的原始 id
和 year
值。
这是我的数据。
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
这是我理想的结果。这是我亲手做的。如果 id
/year
对具有 x
、y
或 z
的非 NA 值,但这不是年份的最后一个值,那么我希望它是 NA。
例如,a
在所有年份中都有 z
的非 NA 值,因此其最后一个 z
值为 5
并且在列 z
结果 table,我想要除 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
这是我到目前为止的分析过程。我认为我的第一步似乎没问题。我应该澄清一下,我正在处理的真实数据每天都有频率。为了简单起见,我将示例数据保持在很小的范围内。
> 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
第二步似乎也可以。我的理想结果中的一些行在这里。
> 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
但我知道我的第三步是错误的,因为它破坏了 last_
列和 year
之间的关系,并且只是将所有内容折叠成一个 table 不包含任何内容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
关于如何重回正轨有什么建议吗?提前谢谢你。
也许这样的解决方案会有用
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
由 reprex package (v2.0.1)
于 2021-11-24 创建
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
由 reprex package (v2.0.1)
于 2021-11-24 创建
也许这有帮助
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)))
通过考虑每列的非 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)
根据每列按 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)]
将所有年份不相同的值更改为 NA。
dat[,':='(x = ifelse(Max_YearX != year, NA, x),
y = ifelse(Max_YearY != year, NA, y),
z = ifelse(Max_YearZ != year, NA, z))]
只保留必需的列
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
我无法从我正在处理的一些数据中提取一些信息。我想提取每个 year
中每个 id
的最后一个非 NA 值,并将这些结果收集在 table 中,它将这些值与它们的原始 id
和 year
值。
这是我的数据。
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
这是我理想的结果。这是我亲手做的。如果 id
/year
对具有 x
、y
或 z
的非 NA 值,但这不是年份的最后一个值,那么我希望它是 NA。
例如,a
在所有年份中都有 z
的非 NA 值,因此其最后一个 z
值为 5
并且在列 z
结果 table,我想要除 a
.
> 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
这是我到目前为止的分析过程。我认为我的第一步似乎没问题。我应该澄清一下,我正在处理的真实数据每天都有频率。为了简单起见,我将示例数据保持在很小的范围内。
> 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
第二步似乎也可以。我的理想结果中的一些行在这里。
> 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
但我知道我的第三步是错误的,因为它破坏了 last_
列和 year
之间的关系,并且只是将所有内容折叠成一个 table 不包含任何内容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
关于如何重回正轨有什么建议吗?提前谢谢你。
也许这样的解决方案会有用
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
由 reprex package (v2.0.1)
于 2021-11-24 创建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
由 reprex package (v2.0.1)
于 2021-11-24 创建也许这有帮助
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)))
通过考虑每列的非 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)
根据每列按 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)]
将所有年份不相同的值更改为 NA。
dat[,':='(x = ifelse(Max_YearX != year, NA, x),
y = ifelse(Max_YearY != year, NA, y),
z = ifelse(Max_YearZ != year, NA, z))]
只保留必需的列
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