具有特定字符串的 Dataframe 的特定行之间的差异

ee7vknir  于 2023-04-09  发布在  其他
关注(0)|答案(2)|浏览(136)

我有一个dataframe df,我需要创建一个新的列delay,当列TEXT等于特定字符串时,计算列TIME的特定行之间的差异:P_S1 - TEXT_W1之间的差异;P_S2 - TEXT_W2。在这个例子中只有两个差异,但在真实的的数据集中有更多的差异。
请参见下面的示例:

|   ID          |   TEXT        |   TIME    |   delay   |
|   P48_1_st    |   TEXT_W1[1]  |   1669    |   NA      |
|   P48_1_st    |   TEXT_W1     |   1669    |   NA      |
|   P48_1_st    |   P_S1        |   1748    |   79      |
|   P48_1_st    |   TEXT_W1[2]  |   2377    |   NA      |
|   P48_1_st    |   TEXT_W2[1]  |   3091    |   NA      |
|   P48_1_st    |   TEXT_W2     |   3093    |   NA      |
|   P48_1_st    |   P_S2        |   3156    |   63      |
|   P48_1_st    |   TEXT_W2[2]  |   3562    |   NA      |
|   P48_1_st    |   TEXT_W2[1]  |   8237    |   NA      |
|   P48_1_st    |   A_P_S2      |   8319    |   NA      |
|   P48_1_st    |   TEXT_W2[5]  |   8379    |   NA      |
|   P48_1_st    |   TEXT_W1[1]  |   8380    |   NA      |
|   P48_1_st    |   A_P_S1      |   8447    |   NA      |
|   P48_1_st    |   TEXT_W1[3]  |   8507    |   NA      |
|   P48_1_st    |   TEXT_W1[1]  |   8700    |   NA      |
|   P48_1_st    |   P_S1[2]     |   8788    |   NA      |
|   P48_1_st    |   TEXT_W1[6]  |   8848    |   NA      |
|   P48_1_st    |   TEXT_W2     |   9144    |   NA      |
|   P48_1_st    |   TEXT_W2     |   9168    |   NA      |
|   P48_1_st    |   TEXT_W2[1]  |   9282    |   NA      |
|   P48_1_st    |   P_S2[2]     |   9343    |   NA      |
|   P48_1_st    |   TEXT_W2[6]  |   9403    |   NA      |
|   P48_1_st    |   TEXT_W2[1]  |   9441    |   NA      |
|   P48_1_st    |   TEXT_W2[4]  |   9441    |   NA      |
|   P48_1_st    |   TEXT_W2[1]  |   9443    |   NA      |
|   P48_1_st    |   P_S2[2]     |   9513    |   NA      |
|   P48_1_st    |   TEXT_W2[6]  |   9573    |   NA      |
|   P48_2_st    |   TEXT_W1[1]  |   6148    |   NA      |
|   P48_2_st    |   TEXT_W1     |   6154    |   NA      |
|   P48_2_st    |   P_S1        |   6234    |   80      |
|   P48_2_st    |   TEXT_W1[2]  |   6689    |   NA      |
|   P48_2_st    |   TEXT_W2[1]  |   6911    |   NA      |
|   P48_2_st    |   TEXT_W2     |   6915    |   NA      |
|   P48_2_st    |   P_S2        |   7002    |   87      |
|   P48_2_st    |   TEXT_W2[2]  |   7210    |   NA      |
|   P48_2_st    |   TEXT_W2[1]  |   10602   |   NA      |
|   P48_2_st    |   A_P_S2      |   10670   |   NA      |
|   P48_2_st    |   TEXT_W2[5]  |   10731   |   NA      |
|   P48_2_st    |   TEXT_W1     |   11250   |   NA      |
|   P48_2_st    |   TEXT_W1     |   11251   |   NA      |
|   P48_2_st    |   TEXT_W1     |   11252   |   NA      |
|   P48_2_st    |   TEXT_W1     |   11252   |   NA      |    
|   P48_2_st    |   TEXT_W1     |   11264   |   NA      |
|   P48_2_st    |   TEXT_W1     |   11265   |   NA      |
|   P48_2_st    |   TEXT_W1[1]  |   11266   |   NA      |
|   P48_2_st    |   A_P_S1      |   11353   |   NA      |
|   P48_2_st    |   TEXT_W1[3]  |   11514   |   NA      |
|   P48_2_st    |   TEXT_W2[1]  |   11775   |   NA      |
|   P48_2_st    |   P_S2[2]     |   11865   |   NA      |
|   P48_2_st    |   TEXT_W2[6]  |   12052   |   NA      |
i86rm4rw

i86rm4rw1#

试试看

library(dplyr)
library(stringr)
out <- df1 %>%
  mutate(grp = cumsum(lag(str_detect(TEXT, "^P_S\\d+$"), default = TRUE))) %>%
  group_by(ID, grp) %>% 
  mutate(delay2 = (TIME[str_detect(TEXT, "^P_S\\d+$")][1] - 
    TIME[str_detect(TEXT, "^TEXT_W\\d+$")][1]) * 
    NA^str_detect(TEXT, "^P_S\\d+$", negate = TRUE)) %>%
  ungroup %>%
  dplyr::select(-grp)
  • 输出
> out$delay
 [1] NA NA 79 NA NA NA 63 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 80 NA NA NA 87 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[50] NA
> out$delay2
 [1] NA NA 79 NA NA NA 63 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 80 NA NA NA 87 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[50] NA

数据

df1 <- structure(list(ID = c("P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", 
"P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", 
"P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", 
"P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", 
"P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", "P48_1_st", "P48_2_st", 
"P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st", 
"P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st", 
"P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st", 
"P48_2_st", "P48_2_st", "P48_2_st", "P48_2_st"), TEXT = c("TEXT_W1[1]", 
"TEXT_W1", "P_S1", "TEXT_W1[2]", "TEXT_W2[1]", "TEXT_W2", "P_S2", 
"TEXT_W2[2]", "TEXT_W2[1]", "A_P_S2", "TEXT_W2[5]", "TEXT_W1[1]", 
"A_P_S1", "TEXT_W1[3]", "TEXT_W1[1]", "P_S1[2]", "TEXT_W1[6]", 
"TEXT_W2", "TEXT_W2", "TEXT_W2[1]", "P_S2[2]", "TEXT_W2[6]", 
"TEXT_W2[1]", "TEXT_W2[4]", "TEXT_W2[1]", "P_S2[2]", "TEXT_W2[6]", 
"TEXT_W1[1]", "TEXT_W1", "P_S1", "TEXT_W1[2]", "TEXT_W2[1]", 
"TEXT_W2", "P_S2", "TEXT_W2[2]", "TEXT_W2[1]", "A_P_S2", "TEXT_W2[5]", 
"TEXT_W1", "TEXT_W1", "TEXT_W1", "TEXT_W1", "TEXT_W1", "TEXT_W1", 
"TEXT_W1[1]", "A_P_S1", "TEXT_W1[3]", "TEXT_W2[1]", "P_S2[2]", 
"TEXT_W2[6]"), TIME = c(1669L, 1669L, 1748L, 2377L, 3091L, 3093L, 
3156L, 3562L, 8237L, 8319L, 8379L, 8380L, 8447L, 8507L, 8700L, 
8788L, 8848L, 9144L, 9168L, 9282L, 9343L, 9403L, 9441L, 9441L, 
9443L, 9513L, 9573L, 6148L, 6154L, 6234L, 6689L, 6911L, 6915L, 
7002L, 7210L, 10602L, 10670L, 10731L, 11250L, 11251L, 11252L, 
11252L, 11264L, 11265L, 11266L, 11353L, 11514L, 11775L, 11865L, 
12052L), delay = c(NA, NA, 79L, NA, NA, NA, 63L, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, 80L, NA, NA, NA, 87L, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, 
-50L))
drkbr07n

drkbr07n2#

尝试:

library(dplyr)
library(stringr)

df2 <- df |> 
  mutate(
    # Get the first number in the text to use as grouping variable (this will
    # be combined with ID).
    .group = str_extract(TEXT, "\\d+")
  ) |> 
  group_by(ID, .group) |> 
  mutate(
    delay2 = if_else(
      # We'll complete the delay value in P_S rows (LHS of AND), but only if
      # there's a TEXT_W value in the group (RHS of AND).
      str_detect(TEXT, "^P_S\\d+$") & any(str_detect(TEXT, "^TEXT_W\\d+$")),
      # Perform the subtraction. Use min to get atomic vector.
      # **Replace for function of preference.**
      TIME - min(TIME[str_detect(TEXT, "^TEXT_W\\d+$")]),
      NA_real_
    )
  ) |> 
  ungroup() |> 
  select(-.group)

df2$delay
#  [1] NA NA 79 NA NA NA 63 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# [25] NA NA NA NA NA 80 NA NA NA 87 NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# [49] NA NA

df2$delay2
#  [1] NA NA 79 NA NA NA 63 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# [25] NA NA NA NA NA 80 NA NA NA 87 NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# [49] NA NA

我假设在有多个TEXT_W值的情况下,您希望使用最小值。如果不是这种情况,请替换min函数调用。例如,请参阅组P48_2_st x P_S1。
此解决方案将独立于行的顺序工作。

相关问题