根据多个条件R有条件地变异数据框

Conditionally mutate dataframe based on multiple conditions R

我看过一些类似的问题,但其中 none 与我想做的事情完全相同 - 这就是我问的原因。

我有一个数据框 (dummy_data),其中包含关于给定主题 (ID) 的一些观察结果 (obs) 的索引。数据帧仅包含有意义的数据(换句话说:满足所需条件)。此示例数据中的最后一列包含观察总数 (total_obs)。

ID <-c(rep("item_001",5),rep("item_452",8),rep("item_0001",7),rep("item_31",9),rep("item_007",5))
obs <- c(1,2,3,5,6,3,4,5,7,8,9,12,16,1,2,4,5,6,7,8,2,4,6,7,8,10,13,14,15,3,4,6,7,11)
total_obs <- c(rep(6,5),rep(16,8),rep(9,7),rep(18,9),rep(11,5))

dummy_data <- data.frame(ID, obs, total_obs)

我想根据以下条件创建一个具有 3 个可能值的新列(间隔):“开始”、“中心”、“结束”:

它应该将观察总数 (total_obs) 分成 3 组(基于索引 - 从第一个到最后一个 - 这是存储在 total_obs 列中的值)并分配根据存储在 obs 列中的索引的间隔值。

这是预期的输出:

ID <- c(rep("item_001",5),rep("item_452",8),rep("item_0001",7),rep("item_31",9),rep("item_007",5))
segment <- c(1,2,3,5,6,  3,4,5,7,8,9,12,16, 1,2,4,5,6,7,8, 2,4,6,7,8,10,13,14,15, 3,4,6,7,11)
total_segments <- c(rep(6,5),rep(16,8),rep(9,7),rep(18,9),rep(11,5))
interval <- c("start","start","center","end","end","start","start","start","center","center","center","end","end","start","start","center","center","center","end","end","start","start","start","center","center","center","end","end","end", "start","start","center","center","end")

wanted_data <- data.frame(ID, segment, total_segments, interval)

我想将 dplyr::ntile() 与 dplyr::mutate() 和 dplyr::case_when() 一起使用,但我无法使我的代码正常运行。有什么解决办法吗?

您只需要 dplyr::mutate()dplyr::case_when()。 以下内容应该可以帮助您解决问题。

dummy_data %>%
    mutate(interval = case_when(obs < (total_obs/3) ~ "start",
                                obs < 2*(total_obs/3) ~ "center",
                                TRUE ~ "end"))
# TRUE ~ "end" is the 'else' case when everything else is false

结果略有不同。 我认为应该更仔细地考虑每个间隔的端点在哪里,但如果你知道你在做什么,使用 <=%/%ceil() 的组合应该给出你想要的结果。

首先,因为dummy_data$obs等同于wanted_data$segment,而dummy_data$total_obs等同于wanted_data$total_segments,你只需要重命名这些列即可。

对于间隔列,这是一种创建方法:

  • 根据 segment 列对数据进行分组
  • 创建一列,例如 tile,并用 ntile(segment) 个结果填充它。
  • 创建 interval 列,并使用 case_when 来填充根据 tile 创建的类别标签。意思是,intervaltile=1时填“start”,2时填“center”,3时填“end”。
  • 删除 tile 列。
wanted_data <- dummy_data %>% 
  rename(segment = obs, total_segments = total_obs) %>%
  group_by(total_segments) %>% 
  mutate(tile = ntile(segment, 3)) %>% 
  mutate(interval = case_when(tile == 1~"start", 
                              tile == 2~"center", 
                              tile == 3~"end")) %>% 
  select(-tile)

wanted_data 

# A tibble: 34 × 4
# Groups:   total_segments [5]
   ID       segment total_segments interval
   <chr>      <dbl>          <dbl> <chr>   
 1 item_001       1              6 start   
 2 item_001       2              6 start   
 3 item_001       3              6 center  
 4 item_001       5              6 center  
 5 item_001       6              6 end     
 6 item_452       3             16 start   
 7 item_452       4             16 start   
 8 item_452       5             16 start   
 9 item_452       7             16 center  
10 item_452       8             16 center  
# … with 24 more rows

它与您展示的 wanted_data$interval 略有不同,因为根据您的评论,您说类别划分与 dplyr::ntile() 一样。