根据 R 中的查找 table 替换某些列和行中的 NA
Replace NA's in some columns and rows based on a lookup table in R
下面的可复制数据集。
让我设定场景:我有5个摄像头同时记录的3个物种的检测历史(V1:V10)(1=检测到,0=未检测到)。
摄像机 1 和 2 在第一天和最后一天没有记录,因此 NA 列在 V1 和 V10 列中。
摄像机 5 前两天和后两天没有记录,因此这些 NA。
因为摄像机 2 没有记录到狞猫,摄像机 5 也没有记录到豹子,所以这些行都充满了 NA。
不过,我知道摄像机 2 和 5 在此期间确实工作,因此摄像机 2 的 V2:V9 狞猫和摄像机 2 的豹子 V3:V8 应该有“0” 5.
所以我的问题是:如何用 0 而不是 NA 填充这些单元格?
当摄像机在第一天和最后几天不工作时,我需要维护 NA。
我的实际数据集有数百个物种、相机和日期,所以我无法手动执行此操作。
我一直在努力解决这个问题,但完全没有成功。
我想创建一个查询 table 每个摄像头何时工作但无法弄清楚语法。
感谢任何帮助
camera<-c(rep(1:5,each=3))
species_names<-c("baboon","caracal", "leopard")
species<-c(rep(species_names,5))
V1<-c(NA,NA,NA,NA,NA,NA,0,0,1,1,1,0,NA,NA,NA)
V2<-c(0,1,0,0,NA,0,0,0,1,0,0,1,NA,NA,NA)
V3<-c(1,0,1,0,NA,0,1,1,0,1,0,0,1,0,NA)
V4<-c(0,1,1,1,NA,0,0,0,0,1,1,0,0,0,NA)
V5<-c(1,1,1,0,NA,1,1,1,0,0,1,1,1,0,NA)
V6<-c(1,0,1,1,NA,1,1,1,1,0,0,1,1,1,NA)
V7<-c(0,0,1,0,NA,0,0,1,0,0,0,0,1,0,NA)
V8<-c(1,1,1,1,NA,1,0,0,0,0,1,0,0,0,NA)
V9<-c(0,0,1,0,NA,0,0,1,1,1,1,0,NA,NA,NA)
V10<-c(NA,NA,NA,NA,NA,NA,0,1,0,0,0,0,NA,NA,NA)
dataset<-data.frame(camera,species,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10)
dataset
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA NA NA NA NA NA NA NA NA NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA NA NA NA NA NA NA NA NA
我的数据集应该是这样的:
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA 0 0 0 0 0 0 0 0 NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA 0 0 0 0 0 0 NA NA
我们可以将 across
与 ifelse
语句一起使用:
library(dplyr)
dataset %>%
mutate(across(V2:V9, ~ifelse(camera==2 & species=="caracal", 0,.)),
across(V3:V8, ~ifelse(camera==5 & species=="leopard", 0,.))
)
输出:
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA 0 0 0 0 0 0 0 0 NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA 0 0 0 0 0 0 NA NA
也许你可以选择
library(dplyr)
dataset %>%
group_by(camera) %>%
mutate(across(V1:V10, ~ifelse(any(!is.na(.)) & is.na(.), 0, .))) %>%
ungroup()
哪个returns
# A tibble: 15 x 12
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
<int> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA 0 0 0 0 0 0 0 0 NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA 0 0 0 0 0 0 NA NA
主要思想是,如果一列中的所有观察值都是NA
,则应保留NA
,否则应将NA
替换为0
。
这是一种方法。这使用 tidyverse
函数,因此加载该库。基本思想是首先有一个长数据集,指示相机在哪些天工作,哪些天不工作。像这样:
camera_data<-data.frame(
camera=rep(c(1:5),each=10 ),
Day=rep(paste0("V",1:10), times=5),
Status=c(0,rep(1,8),0,0, rep(1,8),0, rep(1,20), 0,0, rep(1,6),0,0)
)
看起来像这样
camera Day Status
1 1 V1 0
2 1 V2 1
3 1 V3 1
4 1 V4 1
5 1 V5 1
6 1 V6 1
7 1 V7 1
8 1 V8 1
9 1 V9 1
10 1 V10 0
11 2 V1 0
Status
为 1 表示相机正常工作,0 表示损坏。
然后,你需要将你的检测数据旋转得也很长,像这样:
dataset_long<-dataset %>% pivot_longer(cols=V1:V10, names_to="Day", values_to="Presence")
> dataset_long
# A tibble: 150 x 4
camera species Day Presence
<int> <chr> <chr> <dbl>
1 1 baboon V1 NA
2 1 baboon V2 0
3 1 baboon V3 1
4 1 baboon V4 0
5 1 baboon V5 1
6 1 baboon V6 1
7 1 baboon V7 0
8 1 baboon V8 1
9 1 baboon V9 0
10 1 baboon V10 NA
# ... with 140 more rows
现在你可以简单地 left_join
它们并使用 mutate
中的 if_else
找到应该为 0 的 NA
并替换它们:
dataset_long<-dataset_long %>% left_join(camera_data) %>%
mutate(Presence= if_else(is.na(Presence) & Status==1, 0, Presence))
最后,如果您需要以宽格式恢复数据,您可以使用 pivot_wider
来做到这一点并删除额外的 Status
列:
dataset_done<-dataset_long %>%
pivot_wider(id_cols=c(camera,species), names_from=Day, values_from=Presence)
您的最终数据是:
> dataset_done
# A tibble: 15 x 12
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
<int> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA 0 0 0 0 0 0 0 0 NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA 0 0 0 0 0 0 NA NA
一般来说,我发现处理长格式数据比处理宽格式数据容易得多 - 因此旋转通常是很好的第一步。
这确实需要您制作 camera_data table,但我看不出有任何解决办法。
下面的可复制数据集。
让我设定场景:我有5个摄像头同时记录的3个物种的检测历史(V1:V10)(1=检测到,0=未检测到)。 摄像机 1 和 2 在第一天和最后一天没有记录,因此 NA 列在 V1 和 V10 列中。 摄像机 5 前两天和后两天没有记录,因此这些 NA。
因为摄像机 2 没有记录到狞猫,摄像机 5 也没有记录到豹子,所以这些行都充满了 NA。
不过,我知道摄像机 2 和 5 在此期间确实工作,因此摄像机 2 的 V2:V9 狞猫和摄像机 2 的豹子 V3:V8 应该有“0” 5.
所以我的问题是:如何用 0 而不是 NA 填充这些单元格?
当摄像机在第一天和最后几天不工作时,我需要维护 NA。
我的实际数据集有数百个物种、相机和日期,所以我无法手动执行此操作。
我一直在努力解决这个问题,但完全没有成功。 我想创建一个查询 table 每个摄像头何时工作但无法弄清楚语法。
感谢任何帮助
camera<-c(rep(1:5,each=3))
species_names<-c("baboon","caracal", "leopard")
species<-c(rep(species_names,5))
V1<-c(NA,NA,NA,NA,NA,NA,0,0,1,1,1,0,NA,NA,NA)
V2<-c(0,1,0,0,NA,0,0,0,1,0,0,1,NA,NA,NA)
V3<-c(1,0,1,0,NA,0,1,1,0,1,0,0,1,0,NA)
V4<-c(0,1,1,1,NA,0,0,0,0,1,1,0,0,0,NA)
V5<-c(1,1,1,0,NA,1,1,1,0,0,1,1,1,0,NA)
V6<-c(1,0,1,1,NA,1,1,1,1,0,0,1,1,1,NA)
V7<-c(0,0,1,0,NA,0,0,1,0,0,0,0,1,0,NA)
V8<-c(1,1,1,1,NA,1,0,0,0,0,1,0,0,0,NA)
V9<-c(0,0,1,0,NA,0,0,1,1,1,1,0,NA,NA,NA)
V10<-c(NA,NA,NA,NA,NA,NA,0,1,0,0,0,0,NA,NA,NA)
dataset<-data.frame(camera,species,V1,V2,V3,V4,V5,V6,V7,V8,V9,V10)
dataset
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA NA NA NA NA NA NA NA NA NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA NA NA NA NA NA NA NA NA
我的数据集应该是这样的:
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA 0 0 0 0 0 0 0 0 NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA 0 0 0 0 0 0 NA NA
我们可以将 across
与 ifelse
语句一起使用:
library(dplyr)
dataset %>%
mutate(across(V2:V9, ~ifelse(camera==2 & species=="caracal", 0,.)),
across(V3:V8, ~ifelse(camera==5 & species=="leopard", 0,.))
)
输出:
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA 0 0 0 0 0 0 0 0 NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA 0 0 0 0 0 0 NA NA
也许你可以选择
library(dplyr)
dataset %>%
group_by(camera) %>%
mutate(across(V1:V10, ~ifelse(any(!is.na(.)) & is.na(.), 0, .))) %>%
ungroup()
哪个returns
# A tibble: 15 x 12
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
<int> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA 0 0 0 0 0 0 0 0 NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA 0 0 0 0 0 0 NA NA
主要思想是,如果一列中的所有观察值都是NA
,则应保留NA
,否则应将NA
替换为0
。
这是一种方法。这使用 tidyverse
函数,因此加载该库。基本思想是首先有一个长数据集,指示相机在哪些天工作,哪些天不工作。像这样:
camera_data<-data.frame(
camera=rep(c(1:5),each=10 ),
Day=rep(paste0("V",1:10), times=5),
Status=c(0,rep(1,8),0,0, rep(1,8),0, rep(1,20), 0,0, rep(1,6),0,0)
)
看起来像这样
camera Day Status
1 1 V1 0
2 1 V2 1
3 1 V3 1
4 1 V4 1
5 1 V5 1
6 1 V6 1
7 1 V7 1
8 1 V8 1
9 1 V9 1
10 1 V10 0
11 2 V1 0
Status
为 1 表示相机正常工作,0 表示损坏。
然后,你需要将你的检测数据旋转得也很长,像这样:
dataset_long<-dataset %>% pivot_longer(cols=V1:V10, names_to="Day", values_to="Presence")
> dataset_long
# A tibble: 150 x 4
camera species Day Presence
<int> <chr> <chr> <dbl>
1 1 baboon V1 NA
2 1 baboon V2 0
3 1 baboon V3 1
4 1 baboon V4 0
5 1 baboon V5 1
6 1 baboon V6 1
7 1 baboon V7 0
8 1 baboon V8 1
9 1 baboon V9 0
10 1 baboon V10 NA
# ... with 140 more rows
现在你可以简单地 left_join
它们并使用 mutate
中的 if_else
找到应该为 0 的 NA
并替换它们:
dataset_long<-dataset_long %>% left_join(camera_data) %>%
mutate(Presence= if_else(is.na(Presence) & Status==1, 0, Presence))
最后,如果您需要以宽格式恢复数据,您可以使用 pivot_wider
来做到这一点并删除额外的 Status
列:
dataset_done<-dataset_long %>%
pivot_wider(id_cols=c(camera,species), names_from=Day, values_from=Presence)
您的最终数据是:
> dataset_done
# A tibble: 15 x 12
camera species V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
<int> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 baboon NA 0 1 0 1 1 0 1 0 NA
2 1 caracal NA 1 0 1 1 0 0 1 0 NA
3 1 leopard NA 0 1 1 1 1 1 1 1 NA
4 2 baboon NA 0 0 1 0 1 0 1 0 NA
5 2 caracal NA 0 0 0 0 0 0 0 0 NA
6 2 leopard NA 0 0 0 1 1 0 1 0 NA
7 3 baboon 0 0 1 0 1 1 0 0 0 0
8 3 caracal 0 0 1 0 1 1 1 0 1 1
9 3 leopard 1 1 0 0 0 1 0 0 1 0
10 4 baboon 1 0 1 1 0 0 0 0 1 0
11 4 caracal 1 0 0 1 1 0 0 1 1 0
12 4 leopard 0 1 0 0 1 1 0 0 0 0
13 5 baboon NA NA 1 0 1 1 1 0 NA NA
14 5 caracal NA NA 0 0 0 1 0 0 NA NA
15 5 leopard NA NA 0 0 0 0 0 0 NA NA
一般来说,我发现处理长格式数据比处理宽格式数据容易得多 - 因此旋转通常是很好的第一步。
这确实需要您制作 camera_data table,但我看不出有任何解决办法。