根据特定行值将列添加到数据框

Add column to dataframe depending on specific row values

我正在尝试解决对我来说几天以来一直存在的问题。

这是我的 data.frame 的示例,我希望它能与我的真实示例一起使用。

df <- read.table(text = 'ID    Day Count
    33012   9526    4
    35004   9526    4
    37006   9526    4
    37008   9526    4
    21009   1913    3
    24005   1913    3
    25009   1913    3
    22317   2286    2
    37612   2286    2
    25009   14329   1
    48007   9525    0
    88662   9524    0
    1845    9524    0
    8872    2285    0
    49002   1912    0
    1664    1911    0', header = TRUE)

我需要向我的 data.frame 添加一个新列 (new_col),其中包含从 1 到 4 的值。这些 new_col 值必须包括,每个,天 ( x) 天 (x -1) 和天 (x -2),其中 x = 9526、1913、2286、14329(第 Day 列)。

我的输出应该是这样的:

   ID    Day Count  new_col
33012   9526    4     1
35004   9526    4     1
37006   9526    4     1
37008   9526    4     1
21009   1913    3     2
24005   1913    3     2
25009   1913    3     2
22317   2286    2     3
37612   2286    2     3
25009   14329   1     4
48007   9525    0     1
88662   9524    0     1
1845    9524    0     1
8872    2285    0     3
49002   1912    0     2
1664    1911    0     2

new_col 订购的 data.frame 将是:

   ID    Day Count  new_col
33012   9526    4     1
35004   9526    4     1
37006   9526    4     1
37008   9526    4     1
48007   9525    0     1
88662   9524    0     1
1845    9524    0     1
21009   1913    3     2
24005   1913    3     2
25009   1913    3     2
49002   1912    0     2
1664    1911    0     2
22317   2286    2     3
37612   2286    2     3
8872    2285    0     3
25009   14329   1     4

我的真实 data.frame 比示例更复杂(即 Count 列中有更多列和更多值,因此如果我更新问题请耐心等待。

任何建议都会很有帮助。

我不确定我是否完全理解您的问题,但您似乎可以使用 cut() 来实现此目的,如下所示:

x <- c(1913, 2286, 9526, 14329) 
df$new_col <- cut(df$Day, c(-Inf, x, Inf))
df$new_col <- as.numeric(factor(df$new_col, levels=unique(df$new_col)))

这是一个使用 dplyr 包的不可扩展但易于理解的解决方案,我们可以使用 case_when 根据条件重新编码日期:

library(dplyr)
df %>% mutate(new_col = case_when(abs(df$Day - 9526) <= 2 ~ 1,
                                  abs(df$Day - 1913) <= 2 ~ 2,
                                  abs(df$Day - 2286)<= 2 ~ 3,
                                  abs(df$Day - 14329) <= 2 ~ 4)) %>%
    arrange(new_col)

#       ID   Day Count new_col
# 1  33012  9526     4       1
# 2  35004  9526     4       1
# 3  37006  9526     4       1
# 4  37008  9526     4       1
# 5  48007  9525     0       1
# 6  88662  9524     0       1
# 7   1845  9524     0       1
# 8  21009  1913     3       2
# 9  24005  1913     3       2
# 10 25009  1913     3       2
# 11 49002  1912     0       2
# 12  1664  1911     0       2
# 13 22317  2286     2       3
# 14 37612  2286     2       3
# 15  8872  2285     0       3
# 16 25009 14329     1       4

一种更具可扩展性的方法是使用 data.table 包中的 foverlaps,我们准备查找 table 然后与原始 table 和使用 within 键入 join 以确保日期在查找 table 中指定的范围内,以便更好地解释 foverlaps

library(data.table)
# prepare the look up table
x <- c(9526, 1913, 2286, 14329)
dt1 <- data.table(start = x - 2, end = x, new_col = 1:4)
setkey(dt1)
dt1
#    start   end new_col
# 1:  1911  1913       2
# 2:  2284  2286       3
# 3:  9524  9526       1
# 4: 14327 14329       4

# prepare the original table
dt = copy(setDT(df))
dt[, Day2 := Day]

# do a foverlaps
foverlaps(dt, dt1, by.x = c("Day", "Day2"), by.y = c("start", "end"), type = "within", mult = "all", nomatch = 0L)[, .(ID, Day, Count, new_col)][order(new_col)]

#       ID   Day Count new_col
# 1  33012  9526     4       1
# 2  35004  9526     4       1
# 3  37006  9526     4       1
# 4  37008  9526     4       1
# 5  48007  9525     0       1
# 6  88662  9524     0       1
# 7   1845  9524     0       1
# 8  21009  1913     3       2
# 9  24005  1913     3       2
# 10 25009  1913     3       2
# 11 49002  1912     0       2
# 12  1664  1911     0       2
# 13 22317  2286     2       3
# 14 37612  2286     2       3
# 15  8872  2285     0       3
# 16 25009 14329     1       4