在 R 中组合多个具有 NA 值的列,但仅当 none 列有数据时才使用 NA
Combine several columns with NA values in R, but only use NA if none of the columns has data
如果能提供有关如何改进我的代码的建议,我将不胜感激。第二次尝试成功并提供了所需的输出,但我认为这非常乏味。也许有一个更简单的解决方案。
原始数据集包括 8 列,其中包含有关屏幕分辨率的信息。每列代表一组不同的问题,参与者被随机分配到这些问题中,这意味着如果在该特定集合中没有提出解决问题,则插入 NA,尽管参与者可能已经在不同的集合中回答了它。
我对数据进行了匿名化和简化,仅包含我提到的原始八列中的三列:
ID ResSet1 ResSet2 ResSet3
1 NA NA NA
2 NA NA NA
3 NA NA NA
4 NA NA NA
5 NA 1280x800 NA
6 NA NA NA
7 NA NA NA
8 NA NA NA
9 NA 1440x900 NA
10 NA NA 1366x768
11 NA NA NA
12 NA NA NA
13 NA NA NA
14 NA 1366x768 NA
15 NA NA NA
16 NA NA 1920x1080
17 NA NA NA
18 1600x1200 NA NA
19 NA NA NA
20 NA NA 1366x768
21 NA NA 1440x900
22 NA 1680x1050 NA
23 1600x900 NA NA
24 NA NA NA
25 NA NA 1920x1080
26 NA NA NA
27 NA 1440x900 NA
28 NA NA NA
29 NA NA 1600x900
30 1280x800 NA NA
我的目标是将所有集合合并到一个名为 Resolutions 的栏中;但是,仅当特定行在所有 sets/columns 中包含 NA 值时才将其标记为 NA,如果一组包含分辨率,则仅应将分辨率值写入该列。
我尝试了以下依靠 dplyr 和 tidyr 包,这是我的两次尝试。
第一次尝试使用 mutate 和 paste0:
x = test %>% mutate(Resolution = paste0(ResSet1, ResSet2, ResSet3))
结果如下:(原始数据集的输出)
x$Resolution
1] "NANANANANANANA1366x768" "NANA1440x900NANANANANA" "NANANANANANA1344x840NA" "NANANANA1366x768NANANA"
[5] "NA1280x800NANANANANANA" "NANANANANANANA1366x768" "NANANANA1366x768NANANA" "NANANANANANA1536x864NA"
[9] "NA1440x900NANANANANANA" "NANANA1366x768NANANANA" "NANANANANANANA1280x800" "NANANANANA1366x768NANA"
[13] "NANA1408x792NANANANANA" "NA1366x768NANANANANANA" "NANANANANA1920x1080NANA" "NANANA1920x1080NANANANA"
我没有弄清楚如何在使用 paste0 时执行类似 rm.na 的功能,所以在我第二次尝试使用 unite 时;我用“”替换了 NA 字符串,然后用正确的 NA 替换了空单元格。
x2 = test %>% unite(Resolution, ResSet1, ResSet2, ResSet3,
remove = TRUE, sep = "") %>%
mutate(Resolution = str_replace_all(Resolution, "NA", "")) %>%
mutate(Resolution = ifelse(Resolution == "", NA, Resolution))
结果如下所示:(原始数据集的输出)
x2$Resolution
"1366x768" NA "1280x800" "1366x768" "1366x768" "1366x768" NA "1440x900"
这实际上是我需要实现的;然而,这个解决方案对我来说似乎不是很优雅,也许有更简单的方法。
感谢您的建议。
尝试以下操作:
使用:
df <- structure(list(ID = 1:30, ResSet1 = c(NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "1600x1200", NA,
NA, NA, NA, "1600x900", NA, NA, NA, NA, NA, NA, "1280x800"),
ResSet2 = c(NA, NA, NA, NA, "1280x800", NA, NA, NA, "1440x900",
NA, NA, NA, NA, "1366x768", NA, NA, NA, NA, NA, NA, NA, "1680x1050",
NA, NA, NA, NA, "1440x900", NA, NA, NA), ResSet3 = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, "1366x768", NA, NA, NA, NA,
NA, "1920x1080", NA, NA, NA, "1366x768", "1440x900", NA,
NA, NA, "1920x1080", NA, NA, NA, "1600x900", NA)), .Names = c("ID",
"ResSet1", "ResSet2", "ResSet3"), class = "data.frame", row.names = c(NA,
-30L))
然后:
df$newcol <-
apply(df[,-1], 1, function(row) {
if(all(is.na(row))) return(NA)
else return(unique(row[!is.na(row)]))
})
给出:
head(df)
ID ResSet1 ResSet2 ResSet3 newcol
1 1 <NA> <NA> <NA> <NA>
2 2 <NA> <NA> <NA> <NA>
3 3 <NA> <NA> <NA> <NA>
4 4 <NA> <NA> <NA> <NA>
5 5 <NA> 1280x800 <NA> 1280x800
6 6 <NA> <NA> <NA> <NA>
这里使用 unique
是因为即使在您的示例数据中每行没有重复观察,但在您的实际数据中可能是这种情况(据我了解您的问题描述)。如果不是这种情况,您可以省略 unique
。如果有两种不同的分辨率,您可能希望将其包装成例如list
或其他。
coalesce
可用于select几个向量各自值的第一个非NA
值:
library(dplyr)
df <- df %>%
mutate_at(vars(contains('ResSet')), as.character) %>% # ensure all are character, not factor
mutate(Resolutions = coalesce(ResSet1, ResSet2, ResSet3)) # coalesce
tail(df)
#> ID ResSet1 ResSet2 ResSet3 Resolutions
#> 25 25 <NA> <NA> 1920x1080 1920x1080
#> 26 26 <NA> <NA> <NA> <NA>
#> 27 27 <NA> 1440x900 <NA> 1440x900
#> 28 28 <NA> <NA> <NA> <NA>
#> 29 29 <NA> <NA> 1600x900 1600x900
#> 30 30 1280x800 <NA> <NA> 1280x800
您可以在 base R 中轻松完成此操作 - 我假设第一列是 ID,所有其他列都是分辨率列:
df$res <- df[cbind(seq_len(nrow(df)), max.col(!is.na(df[-1]))+1)]
您可以通过组合 gather
和 right_join
来实现这一点。使用这种方法,您不必手动指定所有列,以防您的 data.frame
仅包含 ID
和其他八列。
library(tidyverse)
df %>%
gather(key, resolution, -ID) %>%
select(-key) %>%
na.omit() %>%
right_join(df)
#> Joining, by = "ID"
#> ID resolution ResSet1 ResSet2 ResSet3
#> 1 1 <NA> <NA> <NA> <NA>
#> 2 2 <NA> <NA> <NA> <NA>
#> 3 3 <NA> <NA> <NA> <NA>
#> 4 4 <NA> <NA> <NA> <NA>
#> 5 5 1280x800 <NA> 1280x800 <NA>
#> 6 6 <NA> <NA> <NA> <NA>
#> 7 7 <NA> <NA> <NA> <NA>
#> 8 8 <NA> <NA> <NA> <NA>
#> 9 9 1440x900 <NA> 1440x900 <NA>
#> 10 10 1366x768 <NA> <NA> 1366x768
#> 11 11 <NA> <NA> <NA> <NA>
#> 12 12 <NA> <NA> <NA> <NA>
#> 13 13 <NA> <NA> <NA> <NA>
#> 14 14 1366x768 <NA> 1366x768 <NA>
#> 15 15 <NA> <NA> <NA> <NA>
#> 16 16 1920x1080 <NA> <NA> 1920x1080
#> 17 17 <NA> <NA> <NA> <NA>
#> 18 18 1600x1200 1600x1200 <NA> <NA>
#> 19 19 <NA> <NA> <NA> <NA>
#> 20 20 1366x768 <NA> <NA> 1366x768
#> 21 21 1440x900 <NA> <NA> 1440x900
#> 22 22 1680x1050 <NA> 1680x1050 <NA>
#> 23 23 1600x900 1600x900 <NA> <NA>
#> 24 24 <NA> <NA> <NA> <NA>
#> 25 25 1920x1080 <NA> <NA> 1920x1080
#> 26 26 <NA> <NA> <NA> <NA>
#> 27 27 1440x900 <NA> 1440x900 <NA>
#> 28 28 <NA> <NA> <NA> <NA>
#> 29 29 1600x900 <NA> <NA> 1600x900
#> 30 30 1280x800 1280x800 <NA> <NA>
如果能提供有关如何改进我的代码的建议,我将不胜感激。第二次尝试成功并提供了所需的输出,但我认为这非常乏味。也许有一个更简单的解决方案。
原始数据集包括 8 列,其中包含有关屏幕分辨率的信息。每列代表一组不同的问题,参与者被随机分配到这些问题中,这意味着如果在该特定集合中没有提出解决问题,则插入 NA,尽管参与者可能已经在不同的集合中回答了它。
我对数据进行了匿名化和简化,仅包含我提到的原始八列中的三列:
ID ResSet1 ResSet2 ResSet3
1 NA NA NA
2 NA NA NA
3 NA NA NA
4 NA NA NA
5 NA 1280x800 NA
6 NA NA NA
7 NA NA NA
8 NA NA NA
9 NA 1440x900 NA
10 NA NA 1366x768
11 NA NA NA
12 NA NA NA
13 NA NA NA
14 NA 1366x768 NA
15 NA NA NA
16 NA NA 1920x1080
17 NA NA NA
18 1600x1200 NA NA
19 NA NA NA
20 NA NA 1366x768
21 NA NA 1440x900
22 NA 1680x1050 NA
23 1600x900 NA NA
24 NA NA NA
25 NA NA 1920x1080
26 NA NA NA
27 NA 1440x900 NA
28 NA NA NA
29 NA NA 1600x900
30 1280x800 NA NA
我的目标是将所有集合合并到一个名为 Resolutions 的栏中;但是,仅当特定行在所有 sets/columns 中包含 NA 值时才将其标记为 NA,如果一组包含分辨率,则仅应将分辨率值写入该列。
我尝试了以下依靠 dplyr 和 tidyr 包,这是我的两次尝试。
第一次尝试使用 mutate 和 paste0:
x = test %>% mutate(Resolution = paste0(ResSet1, ResSet2, ResSet3))
结果如下:(原始数据集的输出)
x$Resolution
1] "NANANANANANANA1366x768" "NANA1440x900NANANANANA" "NANANANANANA1344x840NA" "NANANANA1366x768NANANA"
[5] "NA1280x800NANANANANANA" "NANANANANANANA1366x768" "NANANANA1366x768NANANA" "NANANANANANA1536x864NA"
[9] "NA1440x900NANANANANANA" "NANANA1366x768NANANANA" "NANANANANANANA1280x800" "NANANANANA1366x768NANA"
[13] "NANA1408x792NANANANANA" "NA1366x768NANANANANANA" "NANANANANA1920x1080NANA" "NANANA1920x1080NANANANA"
我没有弄清楚如何在使用 paste0 时执行类似 rm.na 的功能,所以在我第二次尝试使用 unite 时;我用“”替换了 NA 字符串,然后用正确的 NA 替换了空单元格。
x2 = test %>% unite(Resolution, ResSet1, ResSet2, ResSet3,
remove = TRUE, sep = "") %>%
mutate(Resolution = str_replace_all(Resolution, "NA", "")) %>%
mutate(Resolution = ifelse(Resolution == "", NA, Resolution))
结果如下所示:(原始数据集的输出)
x2$Resolution
"1366x768" NA "1280x800" "1366x768" "1366x768" "1366x768" NA "1440x900"
这实际上是我需要实现的;然而,这个解决方案对我来说似乎不是很优雅,也许有更简单的方法。
感谢您的建议。
尝试以下操作:
使用:
df <- structure(list(ID = 1:30, ResSet1 = c(NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "1600x1200", NA,
NA, NA, NA, "1600x900", NA, NA, NA, NA, NA, NA, "1280x800"),
ResSet2 = c(NA, NA, NA, NA, "1280x800", NA, NA, NA, "1440x900",
NA, NA, NA, NA, "1366x768", NA, NA, NA, NA, NA, NA, NA, "1680x1050",
NA, NA, NA, NA, "1440x900", NA, NA, NA), ResSet3 = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, "1366x768", NA, NA, NA, NA,
NA, "1920x1080", NA, NA, NA, "1366x768", "1440x900", NA,
NA, NA, "1920x1080", NA, NA, NA, "1600x900", NA)), .Names = c("ID",
"ResSet1", "ResSet2", "ResSet3"), class = "data.frame", row.names = c(NA,
-30L))
然后:
df$newcol <-
apply(df[,-1], 1, function(row) {
if(all(is.na(row))) return(NA)
else return(unique(row[!is.na(row)]))
})
给出:
head(df)
ID ResSet1 ResSet2 ResSet3 newcol
1 1 <NA> <NA> <NA> <NA>
2 2 <NA> <NA> <NA> <NA>
3 3 <NA> <NA> <NA> <NA>
4 4 <NA> <NA> <NA> <NA>
5 5 <NA> 1280x800 <NA> 1280x800
6 6 <NA> <NA> <NA> <NA>
这里使用 unique
是因为即使在您的示例数据中每行没有重复观察,但在您的实际数据中可能是这种情况(据我了解您的问题描述)。如果不是这种情况,您可以省略 unique
。如果有两种不同的分辨率,您可能希望将其包装成例如list
或其他。
coalesce
可用于select几个向量各自值的第一个非NA
值:
library(dplyr)
df <- df %>%
mutate_at(vars(contains('ResSet')), as.character) %>% # ensure all are character, not factor
mutate(Resolutions = coalesce(ResSet1, ResSet2, ResSet3)) # coalesce
tail(df)
#> ID ResSet1 ResSet2 ResSet3 Resolutions
#> 25 25 <NA> <NA> 1920x1080 1920x1080
#> 26 26 <NA> <NA> <NA> <NA>
#> 27 27 <NA> 1440x900 <NA> 1440x900
#> 28 28 <NA> <NA> <NA> <NA>
#> 29 29 <NA> <NA> 1600x900 1600x900
#> 30 30 1280x800 <NA> <NA> 1280x800
您可以在 base R 中轻松完成此操作 - 我假设第一列是 ID,所有其他列都是分辨率列:
df$res <- df[cbind(seq_len(nrow(df)), max.col(!is.na(df[-1]))+1)]
您可以通过组合 gather
和 right_join
来实现这一点。使用这种方法,您不必手动指定所有列,以防您的 data.frame
仅包含 ID
和其他八列。
library(tidyverse)
df %>%
gather(key, resolution, -ID) %>%
select(-key) %>%
na.omit() %>%
right_join(df)
#> Joining, by = "ID"
#> ID resolution ResSet1 ResSet2 ResSet3
#> 1 1 <NA> <NA> <NA> <NA>
#> 2 2 <NA> <NA> <NA> <NA>
#> 3 3 <NA> <NA> <NA> <NA>
#> 4 4 <NA> <NA> <NA> <NA>
#> 5 5 1280x800 <NA> 1280x800 <NA>
#> 6 6 <NA> <NA> <NA> <NA>
#> 7 7 <NA> <NA> <NA> <NA>
#> 8 8 <NA> <NA> <NA> <NA>
#> 9 9 1440x900 <NA> 1440x900 <NA>
#> 10 10 1366x768 <NA> <NA> 1366x768
#> 11 11 <NA> <NA> <NA> <NA>
#> 12 12 <NA> <NA> <NA> <NA>
#> 13 13 <NA> <NA> <NA> <NA>
#> 14 14 1366x768 <NA> 1366x768 <NA>
#> 15 15 <NA> <NA> <NA> <NA>
#> 16 16 1920x1080 <NA> <NA> 1920x1080
#> 17 17 <NA> <NA> <NA> <NA>
#> 18 18 1600x1200 1600x1200 <NA> <NA>
#> 19 19 <NA> <NA> <NA> <NA>
#> 20 20 1366x768 <NA> <NA> 1366x768
#> 21 21 1440x900 <NA> <NA> 1440x900
#> 22 22 1680x1050 <NA> 1680x1050 <NA>
#> 23 23 1600x900 1600x900 <NA> <NA>
#> 24 24 <NA> <NA> <NA> <NA>
#> 25 25 1920x1080 <NA> <NA> 1920x1080
#> 26 26 <NA> <NA> <NA> <NA>
#> 27 27 1440x900 <NA> 1440x900 <NA>
#> 28 28 <NA> <NA> <NA> <NA>
#> 29 29 1600x900 <NA> <NA> 1600x900
#> 30 30 1280x800 1280x800 <NA> <NA>