我有两个巨大的df(特别是第一个),我在这里简化了。
library(tidyverse)
(thewhat <- tibble(sample = 1:10L, y= 1.0, z =2.0))
# A tibble: 10 x 3
sample y z
<int> <dbl> <dbl>
1 1 1. 2.
2 2 1. 2.
3 3 1. 2.
4 4 1. 2.
5 5 1. 2.
6 6 1. 2.
7 7 1. 2.
8 8 1. 2.
9 9 1. 2.
10 10 1. 2.
(thewhere <- tibble(cond = c("a","a","b","c","a"),
init_sample= c(1,3,4,5,7),
duration = c(1,2,2,1,3),
where = c(NA,"y","z","y","z")))
# A tibble: 5 x 4
cond init_sample duration where
<chr> <dbl> <dbl> <chr>
1 a 1. 1. <NA>
2 a 3. 2. y
3 b 4. 2. z
4 c 5. 1. y
5 a 7. 3. z
我想根据thewhat
df的信息将thewhere
df的一些单元“变”为NAs。重要的是,thewhat
是宽格式的,我不想将其转换为长格式(因为我有数百万行)。
我想将thewhere
中指示的样本转换为init_sample
,直到duration
所指示的列的where
。 (如果where
为NA,则表示它适用于除thewhat
之外的sample
的所有列;此处为y
和z
。)
我创建了一个df,NAs
,表示哪个是应该是NA的单元格:
# table with the elements that should be replaced by NA
NAs <- filter(thewhere, cond=="a") %>%
mutate( sample = map2(init_sample, init_sample + duration - 1,seq)) %>%
unnest %>%
select(where, sample)
我尝试了不同的方法,这是我得到的最接近的方法。在下一个mutate
中,我为一列进行了NA转换,我可以手动添加其余的相关列,但在我的实际场景中,我有30列。
# Takes into account the different columns but I need to manually add each relevant column
# and another case for mutate_all when the where is NA:
mutate(thewhat, y = if_else(sample %in% NAs$sample[NAs$where =="y"],
NA_real_, y ))
预期输出如下:
# A tibble: 10 x 3
sample y z
<int> <dbl> <dbl>
1 1 NA NA
2 2 1. 2.
3 3 NA 2.
4 4 NA 2.
5 5 1. 2.
6 6 1. 2.
7 7 1. NA
8 8 1. NA
9 9 1. NA
10 10 1. 2.
也许mutate_at
或mutate_if
可以在这里工作,但我不知道如何。或者map
中的一些purrr
函数可以拯救我,但我无法使其适用于此案例。
(布朗尼指出,如果解决方案仍然存在于整数中,但我也可以使用其他类型的解决方案)。
谢谢, 布鲁诺
答案 0 :(得分:1)
根据说明,我们可以使用map
library(tidyverse)
lst <- NAs %>%
split(.$where)
set_names(names(lst), names(lst)) %>%
map_df(., ~ thewhat[[.x]] %>%
replace(., thewhat$sample %in% lst[[.x]]$sample, NA_real_) ) %>%
bind_cols(thewhat %>%
select(sample), .)
# A tibble: 10 x 3
# sample y z
# <int> <dbl> <dbl>
# 1 1 1 2
# 2 2 1 2
# 3 3 NA 2
# 4 4 NA 2
# 5 5 1 2
# 6 6 1 2
# 7 7 1 NA
# 8 8 1 NA
# 9 9 1 NA
#10 10 1 2