根据多个条件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
创建的类别标签。意思是,interval
在tile
=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()
一样。
我看过一些类似的问题,但其中 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
创建的类别标签。意思是,interval
在tile
=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()
一样。