我正在处理动物行为数据集,并尝试根据另一行中满足的条件创建一个新列(“环境”)。具体来说,如果行为落在行为“o_water”的开始/停止时间之间,我希望新列返回“water”,如果行为落在这些范围之外,则返回“land”。如果不清楚,这里是一个最小的例子:
library(dplyr)
library(magrittr)
otters <- data.frame(
observation_id = 1,
subject = 1,
behavior = c("o_water", "swim", "float", "o_land", "walk", "o_water", "float"),
start_time = c(1,1,2,6,6,11,11),
stop_time = c(5,3,4,10,9,15,14)
)
#this does it, but manually. need to go over very large dataset and search for conditions
otters <- otters %>%
group_by(subject, observation_id, behavior) %>%
mutate(environment = ifelse((start_time >= 1 & stop_time <= 5) |
(start_time >= 11 & stop_time <= 15), "water", "land"))
这是所需的输出。
Groups: subject, observation_id, behavior [5]
observation_id subject behavior start_time stop_time environment
<dbl> <dbl> <fct> <dbl> <dbl> <chr>
1 1 1 o_water 1 5 water
2 1 1 swim 1 3 water
3 1 1 float 2 4 water
4 1 1 o_land 6 10 land
5 1 1 walk 6 9 land
6 1 1 o_water 11 15 water
7 1 1 float 11 14 water
第二组命令是我想要的,但我需要它来搜索并将其应用到整个数据集,而不是键入每个参数。分组是为了在适用的行上执行功能;在完整数据集中,有多个主题和observation_id。
我尝试使用when()和case_when()但没有成功,但我在R方面还很新手,所以希望得到任何帮助!
对我所做的任何失误表示歉意。我在 stackoverflow 上的其他地方找不到类似的问题。
最佳答案
这是使用 dplyr
的另一种方法,它也使用 fuzzyjoin
包。
您可以将 o_water
行为行与 水獭
分开,并将环境
指定为水
。
然后,使用 fuzzy_left_join
将 o_water
行与其余数据合并,其中 start_time
和 end_time
落在 o_water
范围内。
environment
中剩余的 NA
将是非合并行,可以是 land
或其他名称。
library(dplyr)
library(fuzzyjoin)
otters_water <- otters %>%
filter(behavior == "o_water") %>%
mutate(environment = "water") %>%
select(-behavior)
otters %>%
fuzzy_left_join(otters_water,
by = c("subject", "observation_id", "start_time", "stop_time"),
match_fun = list(`==`, `==`, `>=`, `<=`)) %>%
replace_na(list(environment = "land")) %>%
select(c(observation_id.x:stop_time.x, environment))
输出
observation_id.x subject.x behavior start_time.x stop_time.x environment
1 1 1 o_water 1 5 water
2 1 1 swim 1 3 water
3 1 1 float 2 4 water
4 1 1 o_land 6 10 land
5 1 1 walk 6 9 land
6 1 1 o_water 11 15 water
7 1 1 float 11 14 water
关于r - 根据 R 中另一行的条件改变新列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62643036/