R 如果子集为空,则返回NA的函数

R 如果子集为空,则返回NA的函数,r,dplyr,tidyr,R,Dplyr,Tidyr,我想要一个高效的函数或代码片段,它尝试将向量子集,如果子集中没有元素,则返回NA。比如说, v1 = c(1, 1, NA) 代码unique(v1[!is.na(v1)])返回一个很好的条目,但对于 v2 = c(NA, NA, NA) 代码唯一(v2[!is.na(v2)]返回逻辑(0),当此子集操作用作包含每个摘要或摘要的dplyr链的一部分时,返回的逻辑(0)我希望第二个操作返回NA,而不是逻辑(0) 这背后的背景是,我试图使用多个spread命令来解决这个问题。上一个问题的示例数据

我想要一个高效的函数或代码片段,它尝试将向量子集,如果子集中没有元素,则返回
NA
。比如说,

v1 = c(1, 1, NA)
代码
unique(v1[!is.na(v1)])
返回一个很好的条目,但对于

v2 = c(NA, NA, NA)
代码
唯一(v2[!is.na(v2)]
返回
逻辑(0)
,当此子集操作用作包含每个
摘要或
摘要的
dplyr
链的一部分时,返回的
逻辑(0)
我希望第二个操作返回
NA
,而不是
逻辑(0)

这背后的背景是,我试图使用多个
spread
命令来解决这个问题。上一个问题的示例数据:

set.seed(10)
tmp_dat <- data_frame(
    Person = rep(c("greg", "sally", "sue"), each=2),
    Time = rep(c("Pre", "Post"), 3),
    Score1 = round(rnorm(6, mean = 80, sd=4), 0),
    Score2 = round(jitter(Score1, 15), 0),
    Score3 = 5 + (Score1 + Score2)/2
)

> tmp_dat
Source: local data frame [6 x 5]

  Person  Time Score1 Score2 Score3
   <chr> <chr>  <dbl>  <dbl>  <dbl>
1   greg   Pre     80     78   84.0
2   greg  Post     79     80   84.5
3  sally   Pre     75     74   79.5
4  sally  Post     78     78   83.0
5    sue   Pre     81     78   84.5
6    sue  Post     82     81   86.5
现在,如果NA太多,问题就会出现:

# Replace last two entries in the last row with NA's
tmp_dat$Score2[6] <- NA 
tmp_dat$Score3[6] <- NA 

这可以通过
data.table
中的
dcast
轻松完成,该表可以包含多个
value.var

library(data.table)
dcast(setDT(tmp_dat), Person ~paste0("Time.", Time), 
                 value.var = c("Score1", "Score2", "Score3"))
#     Person Score1_Time.Post Score1_Time.Pre Score2_Time.Post Score2_Time.Pre Score3_Time.Post Score3_Time.Pre
#1:   greg               79              80               80              78             84.5            84.0
#2:  sally               78              75               78              74             83.0            79.5
#3:    sue               82              81               NA              78               NA            84.5

如果我们需要使用
dplyr/tidyr
,一个选项是
将“Score”列收集为“long”格式,
列合并为单个列(“Time1”),然后进行
排列

library(dplyr)
library(tidyr)
gather(tmp_dat, Var, Val, Score1:Score3) %>% 
           mutate(TimeN = 'Time', Var = sub("\\D+", "", Var)) %>%
           unite(Time1, TimeN, Time, Var) %>% 
           spread(Time1, Val)
# # A tibble: 3 × 7
#   Person Time_Post_1 Time_Post_2 Time_Post_3 Time_Pre_1 Time_Pre_2 Time_Pre_3
# *  <chr>       <dbl>       <dbl>       <dbl>      <dbl>      <dbl>      <dbl>
#1   greg          79          80        84.5         80         78       84.0
#2  sally          78          78        83.0         75         74       79.5
#3    sue          82          NA          NA         81         78       84.5
库(dplyr)
图书馆(tidyr)
聚集(tmp_数据、变量、Val、分数1:分数3)%>%
突变(TimeN='Time',Var=sub(“\\D+”,“”,Var))%>%
联合(时间1,时间n,时间,变量)%>%
排列(时间1,Val)
##A tible:3×7
#人员时间\u Post\u 1次\u Post\u 2次\u Post\u 3次\u Pre\u 1次\u Pre\u 2次\u Pre\u 3
# *                                         
#1格雷格798084.5807884.0
#2萨利78 83.0 75 74 79.5
#3苏82 NA 81 78 84.5

谢谢@akrun。但是,如果我尝试执行其他
summary
操作,可能返回空向量,
summary
仍将失败。在这些情况下,我希望能够返回占位符。@Alex在
dcast
中,有您使用的
fun.aggregate
。@Alex我使用了dplyr解决方案进行了更新,但如果您正在寻找一些
summary
解决方案,那么示例应该是不同的,第二个示例只是显示我希望这样一个函数存在的上下文。实际例子在问题的第一部分。我添加了一个粗体的问题陈述,希望更清楚。如果您知道您的行总是只返回一个值,只需在末尾添加
[1]
唯一(v2[!is.na(v2)])[1]
。否则,只需定义自己的函数:
uniqueNotNAThanks。但这是否有效?我喜欢结尾的[1]
library(data.table)
dcast(setDT(tmp_dat), Person ~paste0("Time.", Time), 
                 value.var = c("Score1", "Score2", "Score3"))
#     Person Score1_Time.Post Score1_Time.Pre Score2_Time.Post Score2_Time.Pre Score3_Time.Post Score3_Time.Pre
#1:   greg               79              80               80              78             84.5            84.0
#2:  sally               78              75               78              74             83.0            79.5
#3:    sue               82              81               NA              78               NA            84.5
library(dplyr)
library(tidyr)
gather(tmp_dat, Var, Val, Score1:Score3) %>% 
           mutate(TimeN = 'Time', Var = sub("\\D+", "", Var)) %>%
           unite(Time1, TimeN, Time, Var) %>% 
           spread(Time1, Val)
# # A tibble: 3 × 7
#   Person Time_Post_1 Time_Post_2 Time_Post_3 Time_Pre_1 Time_Pre_2 Time_Pre_3
# *  <chr>       <dbl>       <dbl>       <dbl>      <dbl>      <dbl>      <dbl>
#1   greg          79          80        84.5         80         78       84.0
#2  sally          78          78        83.0         75         74       79.5
#3    sue          82          NA          NA         81         78       84.5