tidyr::gather na.rm 缺少数据
tidyr::gather na.rm with missing data
假设我在一个数据框中有多个列来衡量相同的概念,但采用不同的方法(例如,有多种智商测试,学生可以进行其中的任何一种,或者 none根本)。我想将各种方法组合到一个列中(tidyr 的明显用例)。
如果数据是这样的:
mydata <- data.frame(ID = 55:64,
age = c(12, 12, 14, 11, 20, 10, 13, 15, 18, 17),
Test1 = c(100, 90, 88, 115, NA, NA, NA, NA, NA, NA),
Test2 = c(NA, NA, NA, NA, 100, 120, NA, NA, NA, NA),
Test3 = c( NA, NA, NA, NA, NA, NA, 110, NA, 85, 150))
我自然会想要执行这样的操作(请注意,我使用 na.rm = TRUE 是为了不让我的数据集中的许多 NA 获得它们自己的行):
library(tidyr)
tests <- gather(mydata, key=IQSource, value=IQValue, c(Test1, Test2, Test3), na.rm = TRUE)
tests
给我:
ID age IQSource IQValue
1 55 12 Test1 100
2 56 12 Test1 90
3 57 14 Test1 88
4 58 11 Test1 115
15 59 20 Test2 100
16 60 10 Test2 120
27 61 13 Test3 110
29 63 18 Test3 85
30 64 17 Test3 150
问题是我有一个学生(ID=62)在三项中没有任何 IQ分数,我不想输她的其他数据(ID和年龄列中的数据)。
在 tidyr 中,有没有一种方法可以区分,是的,我想删除 NA,因为我至少在收集的一列中确实有数据,但同时又想防止所有数据丢失要收集的列的数目是 NA?)
我认为这对你有用:
# make another data frame which has just ID and whether or not they missed all 3 tests
missing = mydata %>%
mutate(allNA = is.na(Test1) & is.na(Test2) & is.na(Test3)) %>%
select(ID, allNA)
# Gather and keep NAs
tests <- gather(mydata, key=IQSource, value=IQValue, c(Test1, Test2, Test3), na.rm = FALSE)
# Keep the rows that have a IQValue or missed all tests
tests = left_join(tests, missing) %>%
filter(!is.na(IQValue) | allNA)
# Remove duplicated rows of individuals who missed all exams
tests = tests[!is.na(tests$IQValue) | !duplicated(tests[["ID"]]), ]
我没有找到直接的解决方案,但您可以 right_join
返回原来的 data.frame
然后取消选择您不需要的所有列。
library(tidyr)
library(dplyr)
mydata %>%
gather(key, val, Test1:Test3, na.rm = T) %>%
right_join(mydata) %>%
select(-contains("Test"))
#> Joining, by = c("ID", "age")
#> ID age key val
#> 1 55 12 Test1 100
#> 2 56 12 Test1 90
#> 3 57 14 Test1 88
#> 4 58 11 Test1 115
#> 5 59 20 Test2 100
#> 6 60 10 Test2 120
#> 7 61 13 Test3 110
#> 8 62 15 <NA> NA
#> 9 63 18 Test3 85
#> 10 64 17 Test3 150
或者,您当然可以先创建一个包含所有要保留的变量的 data.frame
,然后加入它:
id_data <- select(mydata, ID, age)
mydata %>%
gather(key, val, Test1:Test3, na.rm = T) %>%
right_join(id_data)
如果每个学生只能进行一次智商测试...
library(tidyverse)
mydata %>%
gather(key=IQSource, value=IQValue, Test1:Test3) %>%
group_by(ID) %>%
arrange(IQValue) %>%
slice(1)
ID age IQSource IQValue
1 55 12 Test1 100
2 56 12 Test1 90
3 57 14 Test1 88
4 58 11 Test1 115
5 59 20 Test2 100
6 60 10 Test2 120
7 61 13 Test3 110
8 62 15 Test1 NA
9 63 18 Test3 85
10 64 17 Test3 150
如果每个学生都可以进行多项智商测试...
mydata %>%
# Add an ID with multiple IQ tests
bind_rows(data.frame(ID=65, age=13, Test1=100, Test2=100, Test3=NA)) %>%
gather(key=IQSource, value=IQValue, Test1:Test3) %>%
group_by(ID) %>%
filter(!is.na(IQValue) | all(is.na(IQValue))) %>%
filter(all(!is.na(IQValue)) | !duplicated(IQValue)) %>%
arrange(ID, IQSource)
ID age IQSource IQValue
1 55 12 Test1 100
2 56 12 Test1 90
3 57 14 Test1 88
4 58 11 Test1 115
5 59 20 Test2 100
6 60 10 Test2 120
7 61 13 Test3 110
8 62 15 Test1 NA
9 63 18 Test3 85
10 64 17 Test3 150
11 65 13 Test1 100
12 65 13 Test2 100
假设我在一个数据框中有多个列来衡量相同的概念,但采用不同的方法(例如,有多种智商测试,学生可以进行其中的任何一种,或者 none根本)。我想将各种方法组合到一个列中(tidyr 的明显用例)。
如果数据是这样的:
mydata <- data.frame(ID = 55:64,
age = c(12, 12, 14, 11, 20, 10, 13, 15, 18, 17),
Test1 = c(100, 90, 88, 115, NA, NA, NA, NA, NA, NA),
Test2 = c(NA, NA, NA, NA, 100, 120, NA, NA, NA, NA),
Test3 = c( NA, NA, NA, NA, NA, NA, 110, NA, 85, 150))
我自然会想要执行这样的操作(请注意,我使用 na.rm = TRUE 是为了不让我的数据集中的许多 NA 获得它们自己的行):
library(tidyr)
tests <- gather(mydata, key=IQSource, value=IQValue, c(Test1, Test2, Test3), na.rm = TRUE)
tests
给我:
ID age IQSource IQValue
1 55 12 Test1 100
2 56 12 Test1 90
3 57 14 Test1 88
4 58 11 Test1 115
15 59 20 Test2 100
16 60 10 Test2 120
27 61 13 Test3 110
29 63 18 Test3 85
30 64 17 Test3 150
问题是我有一个学生(ID=62)在三项中没有任何 IQ分数,我不想输她的其他数据(ID和年龄列中的数据)。
在 tidyr 中,有没有一种方法可以区分,是的,我想删除 NA,因为我至少在收集的一列中确实有数据,但同时又想防止所有数据丢失要收集的列的数目是 NA?)
我认为这对你有用:
# make another data frame which has just ID and whether or not they missed all 3 tests
missing = mydata %>%
mutate(allNA = is.na(Test1) & is.na(Test2) & is.na(Test3)) %>%
select(ID, allNA)
# Gather and keep NAs
tests <- gather(mydata, key=IQSource, value=IQValue, c(Test1, Test2, Test3), na.rm = FALSE)
# Keep the rows that have a IQValue or missed all tests
tests = left_join(tests, missing) %>%
filter(!is.na(IQValue) | allNA)
# Remove duplicated rows of individuals who missed all exams
tests = tests[!is.na(tests$IQValue) | !duplicated(tests[["ID"]]), ]
我没有找到直接的解决方案,但您可以 right_join
返回原来的 data.frame
然后取消选择您不需要的所有列。
library(tidyr)
library(dplyr)
mydata %>%
gather(key, val, Test1:Test3, na.rm = T) %>%
right_join(mydata) %>%
select(-contains("Test"))
#> Joining, by = c("ID", "age")
#> ID age key val
#> 1 55 12 Test1 100
#> 2 56 12 Test1 90
#> 3 57 14 Test1 88
#> 4 58 11 Test1 115
#> 5 59 20 Test2 100
#> 6 60 10 Test2 120
#> 7 61 13 Test3 110
#> 8 62 15 <NA> NA
#> 9 63 18 Test3 85
#> 10 64 17 Test3 150
或者,您当然可以先创建一个包含所有要保留的变量的 data.frame
,然后加入它:
id_data <- select(mydata, ID, age)
mydata %>%
gather(key, val, Test1:Test3, na.rm = T) %>%
right_join(id_data)
如果每个学生只能进行一次智商测试...
library(tidyverse)
mydata %>%
gather(key=IQSource, value=IQValue, Test1:Test3) %>%
group_by(ID) %>%
arrange(IQValue) %>%
slice(1)
ID age IQSource IQValue 1 55 12 Test1 100 2 56 12 Test1 90 3 57 14 Test1 88 4 58 11 Test1 115 5 59 20 Test2 100 6 60 10 Test2 120 7 61 13 Test3 110 8 62 15 Test1 NA 9 63 18 Test3 85 10 64 17 Test3 150
如果每个学生都可以进行多项智商测试...
mydata %>%
# Add an ID with multiple IQ tests
bind_rows(data.frame(ID=65, age=13, Test1=100, Test2=100, Test3=NA)) %>%
gather(key=IQSource, value=IQValue, Test1:Test3) %>%
group_by(ID) %>%
filter(!is.na(IQValue) | all(is.na(IQValue))) %>%
filter(all(!is.na(IQValue)) | !duplicated(IQValue)) %>%
arrange(ID, IQSource)
ID age IQSource IQValue 1 55 12 Test1 100 2 56 12 Test1 90 3 57 14 Test1 88 4 58 11 Test1 115 5 59 20 Test2 100 6 60 10 Test2 120 7 61 13 Test3 110 8 62 15 Test1 NA 9 63 18 Test3 85 10 64 17 Test3 150 11 65 13 Test1 100 12 65 13 Test2 100