如何在R中基于具有逻辑值的列移动列值

时间:2019-07-15 18:30:14

标签: r data.table shift

我试图根据数据表中的逻辑条件列按session_id组移动数据。将数据向下移动到TRUE的行。可用的kw数量等于TRUE语句的数量。如果在TRUE行中已经存在kw,则将其保持在该位置。

我尝试用na.locf填充它们,但这不能解决问题,因为某些数据不相同

Original data

enter image description here

tib = structure(list(Row = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58), session_id = c(1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), hour_of_day = c(14.75, 
15, 15.25, 15.5, 15.75, 16, 16.25, 16.5, 16.75, 17, 17.25, 17.5, 
22, 22.25, 22.5, 22.75, 23, 23.25, 23.5, 23.75, 0, 0.25, 0.5, 
0.75, 1, 1.25, 1.5, 14.25, 14.5, 14.75, 15, 15.25, 15.5, 15.75, 
16, 16.25, 16.5, 16.75, 17, 17.25, 17.5, 17.75, 18, 18.25, 18.5, 
18.75, 19, 22, 22.25, 22.5, 22.75, 23, 23.25, 23.5, 23.75, 0, 
0.25, 0.5), kw = c(1.306767902, 1.399948473, 1.399948473, 1.399948473, 
1.399948473, 1.399948473, 1.399948473, 1.399948473, 1.399948473, 
1.399948473, 1.399948473, 0.560427373, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, 1.199276308, 3.600133009, 
3.600133009, 3.600133009, 3.600133009, 3.600133009, 3.600133009, 
2.101325635, NA, NA, NA, NA, 0, 1.399975856, 1.399975856, 1.399975856, 
1.399975856, 1.399975856, 1.399975856, 0.413944861, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA), check = c(TRUE, TRUE, TRUE, 
TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 
TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, 
FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, 
TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 
FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, 
TRUE, TRUE, TRUE, FALSE, FALSE, FALSE)), class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -58L), spec = structure(list(
    cols = list(Row = structure(list(), class = c("collector_double", 
    "collector")), session_id = structure(list(), class = c("collector_double", 
    "collector")), hour_of_day = structure(list(), class = c("collector_double", 
    "collector")), kw = structure(list(), class = c("collector_double", 
    "collector")), check = structure(list(), class = c("collector_logical", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))

我想要这样的数据

Desired output

enter image description here

out = structure(list(Row = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58), session_id = c(1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), hour_of_day = c(14.75, 
15, 15.25, 15.5, 15.75, 16, 16.25, 16.5, 16.75, 17, 17.25, 17.5, 
22, 22.25, 22.5, 22.75, 23, 23.25, 23.5, 23.75, 0, 0.25, 0.5, 
0.75, 1, 1.25, 1.5, 14.25, 14.5, 14.75, 15, 15.25, 15.5, 15.75, 
16, 16.25, 16.5, 16.75, 17, 17.25, 17.5, 17.75, 18, 18.25, 18.5, 
18.75, 19, 22, 22.25, 22.5, 22.75, 23, 23.25, 23.5, 23.75, 0, 
0.25, 0.5), kw = c(1.306767902, 1.399948473, 1.399948473, 1.399948473, 
1.399948473, NA, NA, NA, NA, NA, NA, NA, 1.399948473, 1.399948473, 
1.399948473, 1.399948473, 1.399948473, 1.399948473, 0.560427373, 
NA, NA, NA, NA, NA, NA, NA, NA, 1.199276308, 3.600133009, 3.600133009, 
3.600133009, 3.600133009, 3.600133009, 3.600133009, 2.101325635, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 1.399975856, 
1.399975856, 1.399975856, 1.399975856, 1.399975856, 1.399975856, 
0.413944861, NA, NA, NA), check = c(TRUE, TRUE, TRUE, TRUE, TRUE, 
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, 
TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, 
FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 
TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 
FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 
TRUE, TRUE, FALSE, FALSE, FALSE)), class = c("spec_tbl_df", "tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -58L), spec = structure(list(
    cols = list(Row = structure(list(), class = c("collector_double", 
    "collector")), session_id = structure(list(), class = c("collector_double", 
    "collector")), hour_of_day = structure(list(), class = c("collector_double", 
    "collector")), kw = structure(list(), class = c("collector_double", 
    "collector")), check = structure(list(), class = c("collector_logical", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))

非常感谢您

1 个答案:

答案 0 :(得分:2)

您可以这样做:

daemon=True

这将覆盖kw列,这意味着如果此代码中有错误,您将丢失原始数据。例如,此代码可能不正确,因为它忽略了按session_id进行分组。因此,在测试代码时,建议创建一本全新的专栏文章:

# fill lines where check is TRUE with non-missing kw values    
tib$kw[tib$check == TRUE] <- na.omit(tib$kw)

# overwrite values where check is FALSE with missing
tib$kw[tib$check == FALSE] <- NA

# verify it works in the example
identical(tib$kw, out$kw)
# [1] TRUE
  

可用kw数量等于TRUE语句的数量。

这表明,只要将数据按session_id提前分组,就可以忽略上述session_id。但是,如果确实需要通过session_id完成该操作,则建议使用dplyr或data.table:

tib$v <- tib$kw
tib$v[tib$check == TRUE] <- na.omit(tib$kw)
tib$v[tib$check == FALSE] <- NA