首页 > 解决方案 > 如何根据 R 中列名中的数字标准对数据进行子集化?

问题描述

问题:我有时间序列数据,我想根据每行不同的开始时间和结束时间对其进行子集化。每个时间点每行都有一个值(例如,在“value_1”到“value_5”列中)。

df <- data.frame(ID = c(101, 102, 103, 104, 105),
                 start = c(1, 2, 1, 3, 2),
                 end = c(2, 4, 3, 4, 3),
                 value_1 = c(8, 10, 4, 7, 6),
                 value_2 = c(3, 6, 9, 2, 5),
                 value_3 = c(4, 4, 10, 1, 6),
                 value_4 = c(5, 7, 8, 9, 2),
                 value_5 = c(4, 6, 3, 8, 10))
df

#    ID start end value_1 value_2 value_3 value_4 value_5
# 1 101     1   2       8       3       4       5       4
# 2 102     2   4      10       6       4       7       6
# 3 103     1   3       4       9      10       8       3
# 4 104     3   4       7       2       1       9       8
# 5 105     2   3       6       5       6       2      10

目标:我想创建一个数据框,它只返回每行的开始和结束时间(包括)之间的列的值,并为开始和结束时间之外的任何行值返回 NA,如下所示:

#    ID start end value_1 value_2 value_3 value_4 value_5
# 1 101     1   2       8       3      NA      NA      NA
# 2 102     2   4      NA       6       4       7      NA
# 3 103     1   3       4       9      10      NA      NA
# 4 104     3   4      NA      NA       1       9      NA
# 5 105     2   3      NA       5       6      NA      NA

老实说,我不确定尝试解决这个问题的途径,所以我期待任何想法。这是我第一次在这里提问,所以如果您需要更多信息或有什么令人困惑的地方,请告诉我。谢谢!

标签: r

解决方案


我们可以重塑为“长”格式,然后在转换后将其转换回来

library(dplyr)
library(tidyr)
df %>%
   pivot_longer(starts_with('value')) %>%
   group_by(ID) %>%
   mutate(value = replace(value,
           !row_number() %in% first(start):first(end), NA)) %>% 
   ungroup %>%
   pivot_wider(names_from = name, values_from = value)
# A tibble: 5 x 8
#     ID start   end value_1 value_2 value_3 value_4 value_5
#  <dbl> <dbl> <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
#1   101     1     2       8       3      NA      NA      NA
#2   102     2     4      NA       6       4       7      NA
#3   103     1     3       4       9      10      NA      NA
#4   104     3     4      NA      NA       1       9      NA
#5   105     2     3      NA       5       6      NA      NA

base Rapply

df[-1] <-  t(apply(df[-1], 1, function(x) {
     x[-(1:2)] <- replace(x[-(1:2)], !seq_along(x[-(1:2)]) %in% x[1]:x[2], NA)
     x}))

推荐阅读