[英]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的那些“值” replace
為NA
,按“記錄”分組,對獲得“值” 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.