簡體   English   中英

篩選出非零值,除非該值是其組中唯一的值(SQL或R)

[英]Filtering out non-zero values unless the value is the only one within its group (SQL or R)

我有一個記錄編號數據集,每個記錄的列中都有多個值。 我想生成一個表,其中每個組中的表都返回最小的非負非NA值。 但是,如果該負數或NA對應於該記錄的唯一行,那么我希望它返回NA。

data <- data.frame(record = c(1, 1, 1, 2, 3, 3, 4), value = c(-1, 2, 40, -10, 3, 4, NA))

| record | value |
------------------
|   1    |  -1   |
|   1    |   2   |
|   1    |   40  |
|   2    |  -10  |
|   3    |   3   |
|   3    |   4   |
|   4    |   NA  |
------------------

我想得到

| record |  out  |
------------------
|   1    |   2   |
|   2    |  NA   |
|   3    |   3   |
|   4    |  NA   |
------------------

在RI中嘗試過:

filter(data, value >= 0 | is.na(value))
data %>% group_by(record) %>% summarize(out = min(value))

在MySQL中,我嘗試了

select min(value) as out
from data
where (value >= 0 or value is null))

但是,這兩種解決方案都從表中刪除記錄#2。

如何包含一個子句來檢測每個記錄的行數並且不消除單個記錄?

一種選擇是將小於0的那些“值” replaceNA ,按“記錄”分組,對獲得“值” min的行進行slice ,或者如果所有行均為NA ,則獲取第一行

data %>%
   mutate(value = replace(value, value < 0, NA)) %>% 
   group_by(record) %>% 
   slice(if(all(is.na(value))) 1 else which.min(value))
# A tibble: 4 x 2
# Groups:   record [4]
#  record value
#   <dbl> <dbl>
#1      1     2
#2      2    NA
#3      3     3
#4      4    NA
library(data.table)
setDT(data)

data[, .(out = if(any(pos <- value >= 0, na.rm = T)) 
                  min(value[pos]) 
                else NA_real_)
     , by = record]

#    record out
# 1:      1   2
# 2:      2  NA
# 3:      3   3
# 4:      4  NA

或者,如果您不喜歡在函數參數中進行賦值

data[, {pos <- value >= 0
        .(out = if(any(pos, na.rm = T)) min(value[pos]) else NA_real_)}
     , by = record]

這是sqldf的一個選項。 不知道是否有更有效的SQL選項。 編輯:注釋中給出了一個更簡單的SQL選項

library(sqldf)

sqldf('
select    a.record
          , b.out
from      data a
          left join (
            select    record
                      , min(value) as out
            from      data
            where     value >= 0
            group by  record
          ) b
            on a.record = b.record
group by  a.record
')
#   record out
# 1      1   2
# 2      2  NA
# 3      3   3
# 4      4  NA

這遠非優雅,但如果上述解決方案都不適合您,則可以完全滿足您的需求。

library(dplyr)
data <- data.frame(record = c(1, 1, 1, 2, 3, 3, 4), value = c(-1, 2, 40, -10, 3, 4, NA))
a<-rownames(data[data$value<0|is.na(data$value),])
data$value[as.integer(a)]<-NA

data<-data %>% group_by(record) %>% summarize(out = min(value,na.rm = TRUE))
data$out[data$out=="Inf"]<-NA

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM