使用 R 从数据框中提取数据并将数据存储在未知数量的新列中

Using R to extract data from a dataframe and store data in unknown number of new columns

我有一个数据框如下:

library(dplyr)
df <- data.frame(A=1:20, 
                  B=c(2,1.8,1.6,1.8,4,6,8,10,12,10,8,6,13,14,15,16,16.5,15,14,13))
mutate(df, C = B - lag(B))
A   B     C
1   2.0   NA
2   1.8 -0.2
3   1.6 -0.2
4   1.8  0.2
5   4.0  2.2
6   6.0  2.0
7   8.0  2.0
8   10.0  2.0
9   12.0  2.0
10  10.0 -2.0
11  8.0 -2.0
12  6.0 -2.0
13  13.0  7.0
14  14.0  1.0
15  15.0  1.0
16  16.0  1.0
17  16.5 -0.5
18  15.0 -1.0
19  14.0 -1.0
20  13.0 -1.0

并且我想提取出连续有3个或更多的负值序列并放在单独的列中。因此,例如,将(col C)第 10、11、12 行的值放在新列中,将第 17、18、19、20 行的值放在另一个新列中。这个数据框很大,所以我不知道我会有多少新列。任何帮助,将不胜感激。谢谢

这里有一个带有 rleid 的选项,可以根据列 'C' 的 sign 创建一个 run-length-id 分组,即那些具有相同 [=15= 的相邻元素] 将具有相同的分组 'id',并且当 sign 存在差异时它会递增。然后,我们根据计数 (n()) 值创建列,使其成为特定数字,即 3 或 4

library(dplyr)
library(data.table)
df %>%
   mutate(C = B - lag(B)) %>%
  group_by(grp = rleid(sign(C))) %>%
  mutate(newC3 = if(n() ==3 && all(C < 0)) C else NA,
         newC4 = if(n() == 4 && all(C < 0) C else NA)

要使其自动化,一个选项是 pivot_wider 在使用 rleid 创建分组 ID 并替换值后从 'long' 重塑为 'wide' 格式不否定 NA。这样,我们只得到负值块在单独的列中

library(tidyr)
library(stringr)
df %>%
   mutate(C = B - lag(B)) %>%
   mutate(grp = str_c('C', rleid(sign(C))), 
     C1 = case_when(C >=0 ~ NA_real_, TRUE ~ C)) %>%
   pivot_wider(names_from = grp, values_from = C1)%>%
   select(where(~ sum(!is.na(.)) > 0))

-输出

# A tibble: 20 x 6
#       A     B      C     C2    C4    C7
#   <int> <dbl>  <dbl>  <dbl> <dbl> <dbl>
# 1     1   2   NA     NA        NA    NA
# 2     2   1.8 -0.200 -0.200    NA    NA
# 3     3   1.6 -0.200 -0.200    NA    NA
# 4     4   1.8  0.200 NA        NA    NA
# 5     5   4    2.2   NA        NA    NA
# 6     6   6    2     NA        NA    NA
# 7     7   8    2     NA        NA    NA
# 8     8  10    2     NA        NA    NA
# 9     9  12    2     NA        NA    NA
#10    10  10   -2     NA        -2    NA
#11    11   8   -2     NA        -2    NA
#12    12   6   -2     NA        -2    NA
#13    13  13    7     NA        NA    NA
#14    14  14    1     NA        NA    NA
#15    15  15    1     NA        NA    NA
#16    16  16    1     NA        NA    NA
#17    17  16    0     NA        NA    NA
#18    18  15   -1     NA        NA    -1
#19    19  14   -1     NA        NA    -1
#20    20  13   -1     NA        NA    -1

注意:列名称 'C2'、'C4'、'C7' 基于使用 rleid 创建的 ID。如果我们想重命名,那么可以用 rename_withrename_at

来完成
...
  %>%
   rename_at(vars(matches('^C\d+')), ~ str_c('C', seq_along(.)))