data.frame에 전체 또는 일부 NA(누락 값)가 있는 행을 제거합니다.
이 데이터 프레임에서 다음과 같은 행을 제거하고 싶습니다.
모든 열에 걸쳐 포함됩니다.아래는 제 예시 데이터 프레임입니다.
gene hsap mmul mmus rnor cfam
1 ENSG00000208234 0 NA NA NA NA
2 ENSG00000199674 0 2 2 2 2
3 ENSG00000221622 0 NA NA NA NA
4 ENSG00000207604 0 NA NA 1 2
5 ENSG00000207431 0 NA NA NA NA
6 ENSG00000221312 0 1 2 3 2
기본적으로 아래와 같은 데이터 프레임을 받고 싶습니다.
gene hsap mmul mmus rnor cfam
2 ENSG00000199674 0 2 2 2 2
6 ENSG00000221312 0 1 2 3 2
일부 열에만 포함되므로 다음과 같은 결과도 얻을 수 있습니다.
gene hsap mmul mmus rnor cfam
2 ENSG00000199674 0 2 2 2 2
4 ENSG00000207604 0 NA NA 1 2
6 ENSG00000221312 0 1 2 3 2
다음 항목도 확인:
> final[complete.cases(final), ]
gene hsap mmul mmus rnor cfam
2 ENSG00000199674 0 2 2 2 2
6 ENSG00000221312 0 1 2 3 2
na.omit
.NA
의complete.cases
데이터 프레임의 특정 열만 포함하여 부분적으로 선택할 수 있습니다.
> final[complete.cases(final[ , 5:6]),]
gene hsap mmul mmus rnor cfam
2 ENSG00000199674 0 2 2 2 2
4 ENSG00000207604 0 NA NA 1 2
6 ENSG00000221312 0 1 2 3 2
솔루션이 작동하지 않습니다.사용을 고집하는 경우is.na
그런 다음 다음과 같은 작업을 수행해야 합니다.
> final[rowSums(is.na(final[ , 5:6])) == 0, ]
gene hsap mmul mmus rnor cfam
2 ENSG00000199674 0 2 2 2 2
4 ENSG00000207604 0 NA NA 1 2
6 ENSG00000221312 0 1 2 3 2
하지만 사용하기complete.cases
훨씬 더 명확하고 빠릅니다.
ㅠㅠna.omit(your.data.frame)
두 번째 질문에 대해서는 (명확하게 하기 위해) 다른 질문으로 올려보세요.
tidyr
다음과 같은 새로운 기능이 있습니다.
library(tidyr)
df %>% drop_na()
# gene hsap mmul mmus rnor cfam
# 2 ENSG00000199674 0 2 2 2 2
# 6 ENSG00000221312 0 1 2 3 2
df %>% drop_na(rnor, cfam)
# gene hsap mmul mmus rnor cfam
# 2 ENSG00000199674 0 2 2 2 2
# 4 ENSG00000207604 0 NA NA 1 2
# 6 ENSG00000221312 0 1 2 3 2
행에 NA가 포함되어 있는지 확인하려면 다음 방법을 선호합니다.
row.has.na <- apply(final, 1, function(x){any(is.na(x))})
행에 NA가 있는지 여부를 나타내는 값을 가진 논리 벡터를 반환합니다.이 도구를 사용하여 삭제할 행 수를 확인할 수 있습니다.
sum(row.has.na)
그리고 결국 그것들을 떨어뜨립니다.
final.filtered <- final[!row.has.na,]
NA의 특정 부분이 포함된 행을 필터링하는 경우에는 좀 더 까다로워집니다(예: 'final[,5:6]'을 입력하여 'apply'할 수 있습니다).일반적으로 Joris Meys의 솔루션은 더 우아해 보입니다.
각 행에 유효한 NA 수를 제어하려면 이 기능을 사용해 보십시오.많은 설문 조사 데이터 세트의 경우 빈 질문 응답이 너무 많으면 결과가 엉망이 될 수 있습니다.따라서 특정 임계값이 지나면 삭제됩니다.이 기능을 사용하면 행이 삭제되기 전에 몇 개의 NA를 가질 수 있는지 선택할 수 있습니다.
delete.na <- function(DF, n=0) {
DF[rowSums(is.na(DF)) <= n,]
}
기본적으로 모든 NA가 제거됩니다.
delete.na(final)
gene hsap mmul mmus rnor cfam
2 ENSG00000199674 0 2 2 2 2
6 ENSG00000221312 0 1 2 3 2
또는 허용되는 최대 NA 수를 지정합니다.
delete.na(final, 2)
gene hsap mmul mmus rnor cfam
2 ENSG00000199674 0 2 2 2 2
4 ENSG00000207604 0 NA NA 1 2
6 ENSG00000221312 0 1 2 3 2
하는 경우에는 성이우는경우되를 합니다.data.table
그리고.na.omit()
매개 변수 선 매 를 수 사 용 변 개cols=
.
na.omit.data.table
모든 열이든 선택한 열이든 벤치마크에서 가장 빠릅니다(OP 질문 파트 2).
사용하지 않으려는 경우data.table
,사용하다complete.cases()
.
위에 닐라바위 에닐에위.data.frame
또는complete.cases
보다 빠릅니다.na.omit.data.frame
하지 .cols=
.
벤치마크 결과
다음은 기본값(파란색)을 비교한 것입니다.dplyr
(분홍색),data.table
관측치를 , 누락될 으로 5 개의 및 2에 집합. (노란색) 노개 에 만 삭 인 독 로 5% 개 20% 숫 변 분 부 변 의 대파및 수 세 트데 트관터한이치측개의한 2대 에 수 측 결 색 란 가 으 를 적 립 성 치 능 모 이
특정 데이터 집합의 길이, 너비 및 희소성에 따라 결과가 달라질 수 있습니다.
y축의 로그 축척을 기록합니다.
벤치마크 스크립트
#------- Adjust these assumptions for your own use case ------------
row_size <- 1e6L
col_size <- 20 # not including ID column
p_missing <- 0.05 # likelihood of missing observation (except ID col)
col_subset <- 18:21 # second part of question: filter on select columns
#------- System info for benchmark ----------------------------------
R.version # R version 3.4.3 (2017-11-30), platform = x86_64-w64-mingw32
library(data.table); packageVersion('data.table') # 1.10.4.3
library(dplyr); packageVersion('dplyr') # 0.7.4
library(tidyr); packageVersion('tidyr') # 0.8.0
library(microbenchmark)
#------- Example dataset using above assumptions --------------------
fakeData <- function(m, n, p){
set.seed(123)
m <- matrix(runif(m*n), nrow=m, ncol=n)
m[m<p] <- NA
return(m)
}
df <- cbind( data.frame(id = paste0('ID',seq(row_size)),
stringsAsFactors = FALSE),
data.frame(fakeData(row_size, col_size, p_missing) )
)
dt <- data.table(df)
par(las=3, mfcol=c(1,2), mar=c(22,4,1,1)+0.1)
boxplot(
microbenchmark(
df[complete.cases(df), ],
na.omit(df),
df %>% drop_na,
dt[complete.cases(dt), ],
na.omit(dt)
), xlab='',
main = 'Performance: Drop any NA observation',
col=c(rep('lightblue',2),'salmon',rep('beige',2))
)
boxplot(
microbenchmark(
df[complete.cases(df[,col_subset]), ],
#na.omit(df), # col subset not supported in na.omit.data.frame
df %>% drop_na(col_subset),
dt[complete.cases(dt[,col_subset,with=FALSE]), ],
na.omit(dt, cols=col_subset) # see ?na.omit.data.table
), xlab='',
main = 'Performance: Drop NA obs. in select cols',
col=c('lightblue','salmon',rep('beige',2))
)
행이 유효하지 않은 것으로 간주되는 방법을 보다 효과적으로 제어하려면 다음과 같은 옵션을 사용됩니다.
final <- final[!(is.na(final$rnor)) | !(is.na(rawdata$cfam)),]
위의 내용을 사용하면 다음과 같습니다.
gene hsap mmul mmus rnor cfam
1 ENSG00000208234 0 NA NA NA 2
2 ENSG00000199674 0 2 2 2 2
3 ENSG00000221622 0 NA NA 2 NA
4 ENSG00000207604 0 NA NA 1 2
5 ENSG00000207431 0 NA NA NA NA
6 ENSG00000221312 0 1 2 3 2
다음이 됩니다.
gene hsap mmul mmus rnor cfam
1 ENSG00000208234 0 NA NA NA 2
2 ENSG00000199674 0 2 2 2 2
3 ENSG00000221622 0 NA NA 2 NA
4 ENSG00000207604 0 NA NA 1 2
6 ENSG00000221312 0 1 2 3 2
...만 제거됩니다. 두 행 모두에 입니다.여기서 5행만 제거됩니다. 5행은 두 행 모두에 대한 NA를 포함하는 유일한 행이기 때문입니다.rnor
그리고.cfam
그런 다음 부울 논리를 특정 요구 사항에 맞게 변경할 수 있습니다.
dplyr 패키지를 사용하면 다음과 같이 NA를 필터링할 수 있습니다.
dplyr::filter(df, !is.na(columnname))
수 있는 한 은 일적이고읽을수있는은방한식생접가근지는성반하드를코상당히▁the▁is▁one▁that은방식을 사용하는 것입니다.filter()
및 능기및across()
{dplyr} 패키지의 도우미 기능입니다.
library(dplyr)
vars_to_check <- c("rnor", "cfam")
# Filter a specific list of columns to keep only non-missing entries
df %>%
filter(across(one_of(vars_to_check),
~ !is.na(.x)))
# Filter all the columns to exclude NA
df %>%
filter(across(everything(),
~ !is.na(.)))
# Filter only numeric columns
df %>%
filter(across(where(is.numeric),
~ !is.na(.)))
패키지에도 (dplyr 패키지에는 변형 함수가 있습니다).filter_all
,filter_at
,filter_if
는 같은을 하는 것입니다.
library(dplyr)
vars_to_check <- c("rnor", "cfam")
# Filter a specific list of columns to keep only non-missing entries
df %>%
filter_at(.vars = vars(one_of(vars_to_check)),
~ !is.na(.))
# Filter all the columns to exclude NA
df %>%
filter_all(~ !is.na(.))
# Filter only numeric columns
df %>%
filter_if(is.numeric,
~ !is.na(.))
비NA 값이 하나 이상 있는 행을 반환합니다.
final[rowSums(is.na(final))<length(final),]
그러면 적어도 두 개의 비NA 값이 있는 행이 반환됩니다.
final[rowSums(is.na(final))<(length(final)-1),]
첫 번째 질문으로, 저는 모든 NA를 제거하는 데 익숙한 코드를 가지고 있습니다.@Gregor가 더 단순하게 해주셔서 감사합니다.
final[!(rowSums(is.na(final))),]
두 번째 질문의 경우, 코드는 이전 솔루션의 대안일 뿐입니다.
final[as.logical((rowSums(is.na(final))-5)),]
-5는 데이터의 열 수입니다.이렇게 하면 rowSums가 최대 5개가 되고 뺄셈 후에는 0이 되기 때문에 모든 NA가 포함된 행이 제거됩니다.이번에는 as.logical이 필요합니다.
이를 위해 부분 집합 함수를 사용할 수도 있습니다.
finalData<-subset(data,!(is.na(data["mmul"]) | is.na(data["rnor"])))
이렇게 하면 mmul과 rnor 모두에서 NA가 없는 행만 표시됩니다.
dplyr 1.0.4는 두 개의 동반 함수를 도입했습니다.filter
은 그은입니다.if_any()
그리고.if_all()
.if_all()
동반 함수는 이 경우에 특히 유용합니다.
모든 열에서 NA를 포함하는 행을 제거하는 방법
df %>%
filter(if_all(everything(), ~ !is.na(.x)))
이 행은 열에 NA가 없는 행만 유지합니다.
일부 열의 NA만 포함하는 행을 제거하는 방법
cols_to_check = c("rnor", "cfam")
df %>%
filter(if_all(cols_to_check, ~ !is.na(.x)))
이 줄은 지정된 열(cols_to_check)에 NA가 있는지 확인하고 그렇지 않은 행만 유지합니다.
을 가정하여dat
으로서임데, 예출력다사용달음수있다성습을 사용하여 예상 출력을 할 수 .
1.rowSums
> dat[!rowSums((is.na(dat))),]
gene hsap mmul mmus rnor cfam
2 ENSG00000199674 0 2 2 2 2
6 ENSG00000221312 0 1 2 3 2
2.lapply
> dat[!Reduce('|',lapply(dat,is.na)),]
gene hsap mmul mmus rnor cfam
2 ENSG00000199674 0 2 2 2 2
6 ENSG00000221312 0 1 2 3 2
저는 신시사이저입니다:).여기서 저는 답을 하나의 기능으로 결합했습니다.
#' keep rows that have a certain number (range) of NAs anywhere/somewhere and delete others
#' @param df a data frame
#' @param col restrict to the columns where you would like to search for NA; eg, 3, c(3), 2:5, "place", c("place","age")
#' \cr default is NULL, search for all columns
#' @param n integer or vector, 0, c(3,5), number/range of NAs allowed.
#' \cr If a number, the exact number of NAs kept
#' \cr Range includes both ends 3<=n<=5
#' \cr Range could be -Inf, Inf
#' @return returns a new df with rows that have NA(s) removed
#' @export
ez.na.keep = function(df, col=NULL, n=0){
if (!is.null(col)) {
# R converts a single row/col to a vector if the parameter col has only one col
# see https://radfordneal.wordpress.com/2008/08/20/design-flaws-in-r-2-%E2%80%94-dropped-dimensions/#comments
df.temp = df[,col,drop=FALSE]
} else {
df.temp = df
}
if (length(n)==1){
if (n==0) {
# simply call complete.cases which might be faster
result = df[complete.cases(df.temp),]
} else {
# credit: http://stackoverflow.com/a/30461945/2292993
log <- apply(df.temp, 2, is.na)
logindex <- apply(log, 1, function(x) sum(x) == n)
result = df[logindex, ]
}
}
if (length(n)==2){
min = n[1]; max = n[2]
log <- apply(df.temp, 2, is.na)
logindex <- apply(log, 1, function(x) {sum(x) >= min && sum(x) <= max})
result = df[logindex, ]
}
return(result)
}
delete.dirt <- function(DF, dart=c('NA')) {
dirty_rows <- apply(DF, 1, function(r) !any(r %in% dart))
DF <- DF[dirty_rows, ]
}
mydata <- delete.dirt(mydata)
위 함수는 열에 'NA'가 있는 모든 행을 데이터 프레임에서 삭제하고 결과 데이터를 반환합니다. 여값을확면과 같은 여러 ,NA
그리고.?
바꾸다dart=c('NA')
의 함수 파라미터에.dart=c('NA', '?')
제 생각에는 이 문제는 다음과 같은 방식으로 더 우아하게 해결될 수 있을 것 같습니다.
m <- matrix(1:25, ncol = 5)
m[c(1, 6, 13, 25)] <- NA
df <- data.frame(m)
library(dplyr)
df %>%
filter_all(any_vars(is.na(.)))
#> X1 X2 X3 X4 X5
#> 1 NA NA 11 16 21
#> 2 3 8 NA 18 23
#> 3 5 10 15 20 NA
모든 열에 NA가 있는 행만 제거하려는 경우 솔루션은 다음과 같습니다.
df %>%
filter(!if_all(everything(), ~ is.na(.)))
또 다른 옵션은 다음과 같습니다.na_omit
의 기능.collapse
:
na_omit(df)
# gene hsap mmul mmus rnor cfam
# 1 ENSG00000199674 0 2 2 2 2
# 2 ENSG00000221312 0 1 2 3 2
또는 선택한 열의 경우:
na_omit(df, cols = c("rnor", "cfam")) #Alternatively, works with a function, index or logical vector
# gene hsap mmul mmus rnor cfam
# 1 ENSG00000199674 0 2 2 2 2
# 2 ENSG00000207604 0 NA NA 1 2
# 3 ENSG00000221312 0 1 2 3 2
collapse::na_omit
다음을 포함하여 여기에 제공되는 다른 솔루션보다 빠릅니다.data.table::na.omit
그리고.tidyr::drop_na
:
#Using data from https://stackoverflow.com/a/48830183/13460602
mb <-
microbenchmark(
collapse = na_omit(dt),
dt = na.omit(dt),
base = na.omit(df),
complete.cases = df[complete.cases(df), ],
tidyr = drop_na(df)
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# collapse 70.6927 130.5431 191.9058 156.6320 217.1957 915.6074 100
# dt 76.5151 130.7049 195.9737 172.6981 215.2754 735.1839 100
# base 406.3456 778.5028 900.1791 860.7407 1005.6444 2009.2036 100
# complete.cases 295.6927 497.8572 649.3397 575.9408 715.9452 2137.3366 100
# tidyr 83.4586 145.3758 207.3149 180.9264 242.0750 838.3654 100
언급URL : https://stackoverflow.com/questions/4862178/remove-rows-with-all-or-some-nas-missing-values-in-data-frame
'programing' 카테고리의 다른 글
ggplot2 꺽은선형 차트는 "geom_path: 각 그룹은 하나의 관측치로만 구성됩니다.그룹 에스테틱을 조정할 필요가 있습니까?" (0) | 2023.06.06 |
---|---|
파이어스토어의 문서에 하위 컬렉션을 추가하는 방법은 무엇입니까? (0) | 2023.06.06 |
픽셀을 dp로 변환 (0) | 2023.06.01 |
단추의 모서리를 둥글게 만드는 방법은? (0) | 2023.06.01 |
Ruby에서 DateTime 및 Time으로 변환 (0) | 2023.06.01 |