ডেটা.ফ্রেমে সমস্ত বা কিছু এনএ (অনুপস্থিত মান) সহ সারিগুলি সরান


851

আমি এই ডেটা ফ্রেমের লাইনগুলি সরাতে চাই যে:

ক) ধারণ করে 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

খ) ধারণ করে NAশুধুমাত্র কিছু কলামে গুলি , তাই আমি এই ফলাফলের পেতে পারেন:

             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

উত্তর:


1062

এছাড়াও পরীক্ষা করুন complete.cases:

> 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কেবলমাত্র সমস্তগুলি মুছে ফেলার জন্য দুর্দান্ত NAcomplete.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করা অনেক বেশি স্পষ্ট এবং দ্রুত।


8
পিছনে থাকা কমাটির তাৎপর্য কী final[complete.cases(final),]?
হার্টজস্প্রং

6
@hertzsprung আপনার কলামগুলি নয়, সারি নির্বাচন করা দরকার। আর কীভাবে করবেন?
জোরিস মাইস

4
একটি সরল অবহেলা আছে complete.cases? আমি যদি নখের পরিবর্তে এনএ দিয়ে সারি রাখতে চাইতাম? final[ ! complete.cases(final),]সহযোগিতা করে না ...
tumultous_rooster

2
finalডাটাফ্রেম পরিবর্তনশীল?
মোর্স

1
@ প্রীতেক সত্যই, এটি।
জোরিস মাইস

256

ব্যবহার করে দেখুন na.omit(your.data.frame)। দ্বিতীয় প্রশ্ন হিসাবে, এটি অন্য প্রশ্ন হিসাবে পোস্ট করার চেষ্টা করুন (স্পষ্টতার জন্য)।


na.omit সারিগুলি ড্রপ করে তবে সারি সংখ্যাগুলি সংরক্ষণ করে। আপনি কীভাবে এটি ঠিক করবেন যাতে এটি সঠিকভাবে নম্বরযুক্ত হয়?
বিয়ার

3
@ বার করুন যদি আপনি সারি সংখ্যা সম্পর্কে চিন্তা না করেন তবে ঠিক করুন rownames(x) <- NULL
রোমান Luštrik

দয়া করে নোট করুন যে কোনও কলামে na.omit()থাকা সারিগুলি ফোঁটাNA
ভিক্টর ম্যাক্সওয়েল

116

tidyrএকটি নতুন ফাংশন আছে drop_na:

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

3
পাইপ এবং এর মধ্যে কোনও আসল সংযোগ নেই drop_na। উদাহরণস্বরূপ, df %>% drop_na(), df %>% na.omit()এবং drop_na(df)সব মূলত সমতুল্য।
ইস্তা

4
@ ইসতা আমি একমত নই na.omitবাদ দেওয়া মামলার সূচির মতো অতিরিক্ত তথ্য যুক্ত করে এবং - আরও গুরুত্বপূর্ণভাবে - আপনাকে কলাম নির্বাচন করতে দেয় না - এটিই এখানে drop_naজ্বলজ্বল করে।
lukeA

3
অবশ্যই, আমার বক্তব্যটি হ'ল পাইপের সাথে এর কোনও যোগসূত্র নেই। আপনি na.omitপাইপগুলির সাথে বা তার ছাড়াও ব্যবহার করতে পারেন , যেমন আপনি drop_naপাইপের সাথে বা ব্যবহার ছাড়াই করতে পারেন ।
ইস্তা

1
সত্য, পাইপগুলির সাথে মোটেই কিছুই করার নেই। ড্রপ_না () অন্য যেহেতু কেবল একটি ফাংশন এবং যেমন, সরাসরি বা পাইপ ব্যবহার করে কল করা যায়। দুর্ভাগ্যক্রমে, ড্রপ_না (), উল্লিখিত অন্যান্য পদ্ধতির মতো, চিড়িয়াখানা বা এক্সটিএস অবজেক্টের ধরণের ক্ষেত্রে ব্যবহার করা যাবে না। এটি কারও কারও জন্য সমস্যা হতে পারে।
ডেভ

ঠিক আছে, তাই আমি উত্তরটি সম্পাদনা করেছি যাতে এটি পাইপের উল্লেখ না করে।
আর্থার ইপ

91

সারিগুলিতে কোনও এনএ রয়েছে কিনা তা পরীক্ষা করার জন্য আমি নিম্নলিখিত উপায়টিকে পছন্দ করি:

row.has.na <- apply(final, 1, function(x){any(is.na(x))})

এটি একক সারিতে কোনও এনএ আছে কিনা তা চিহ্নিত করে মান সহ লজিকাল ভেক্টরকে ফেরত দেয়। আপনাকে কতটি সারি বাদ দিতে হবে তা দেখতে আপনি এটি ব্যবহার করতে পারেন:

sum(row.has.na)

এবং অবশেষে সেগুলি ফেলে দিন

final.filtered <- final[!row.has.na,]

এনএ এর নির্দিষ্ট অংশের সাথে সারিগুলি ফিল্টার করার জন্য এটি কিছুটা জটিল হয়ে যায় (উদাহরণস্বরূপ, আপনি 'প্রয়োগ করতে' ফাইনাল [, 5: 6] খাওয়াতে পারেন) feed সাধারণত, জরিস মাইসের সমাধানটি আরও মার্জিত বলে মনে হয়।


2
এটি অত্যন্ত ধীর। উদাহরণস্বরূপ পূর্বোক্ত সম্পূর্ণ কোডেস () সমাধানের চেয়ে অনেক ধীর। কমপক্ষে, আমার ক্ষেত্রে, এক্সটিএস ডেটাতে।
ডেভ

3
rowSum(!is.na(final))ভাল চেয়ে উপযুক্ত মনেapply()
sindri_baldur

45

সারিগুলি কীভাবে অবৈধ বলে মনে করা হয় তার উপরে যদি আপনি আরও বেশি নিয়ন্ত্রণ চান তবে অন্য একটি বিকল্প

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 টি সারি সরানো হয় কারণ এটি উভয় rnorএবং উভয় জন্যই এনএ যুক্ত একমাত্র সারি cfam। তারপরে বুলিয়ান যুক্তিটি নির্দিষ্ট প্রয়োজনীয়তার সাথে মাপসই করা যায়।


5
তবে আপনি কীভাবে এটি ব্যবহার করতে পারেন যদি আপনি প্রত্যেকটি টাইপ না করেই অনেকগুলি কলামগুলি পরীক্ষা করতে চান তবে আপনি কি একটি পরিসীমা ফাইনাল ব্যবহার করতে পারেন [, 4: 100]?
হারমান টুথ্রোট

40

আপনি যদি প্রতিটি সারির জন্য কতগুলি এনএ বৈধ, তার উপর নিয়ন্ত্রণ রাখতে চান তবে এই ফাংশনটি ব্যবহার করে দেখুন। অনেক সমীক্ষার ডেটা সেটগুলির জন্য, অনেকগুলি ফাঁকা প্রশ্নের প্রতিক্রিয়া ফলাফলগুলি নষ্ট করতে পারে। সুতরাং সেগুলি একটি নির্দিষ্ট দোরের পরে মুছে ফেলা হয়। এই ফাংশনটি আপনাকে সারিটি মোছার আগে কয়টি এনএ থাকতে পারে তা চয়ন করতে দেয়:

delete.na <- function(DF, n=0) {
  DF[rowSums(is.na(DF)) <= n,]
}

ডিফল্টরূপে, এটি সমস্ত এনএগুলি দূর করবে:

delete.na(final)
             gene hsap mmul mmus rnor cfam
2 ENSG00000199674    0    2    2    2    2
6 ENSG00000221312    0    1    2    3    2

অথবা অনুমোদিত এনএর সর্বাধিক সংখ্যা নির্দিষ্ট করুন:

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

39

যদি পারফরম্যান্স অগ্রাধিকার হয় তবে ব্যবহার করুন data.tableএবং na.omit()optionচ্ছিক প্যারাম সহ cols=

na.omit.data.table সমস্ত কলামের জন্য বা নির্বাচিত কলামগুলির জন্য (নীচে দেখুন অংশটি) আমার বেঞ্চমার্কে (নীচে দেখুন) দ্রুততম OP

আপনি যদি ব্যবহার করতে না চান তবে data.tableব্যবহার করুন complete.cases()

একটি ভ্যানিলা উপর data.frame, complete.casesদ্রুত চেয়ে na.omit()বা dplyr::drop_na()। লক্ষ্য করুন যে na.omit.data.frameসমর্থন করে না cols=

বেঞ্চমার্ক ফলাফল

এখানে বেস (নীল), dplyr(গোলাপী) এবং data.table(হলুদ) পদ্ধতির তুলনা হয় সমস্ত বাদ দেওয়ার জন্য বা অনুপস্থিত পর্যবেক্ষণগুলি নির্বাচন করার জন্য, 20 টি সংখ্যার ভেরিয়েবলের 1 মিলিয়ন পর্যবেক্ষণের অনুমানীয় ডেটাসেটে, নিখোঁজ হওয়ার 5% সম্ভাবনা রয়েছে এবং একটি অংশ 2 এর জন্য 4 ভেরিয়েবলের সাবসেট।

আপনার ফলাফলগুলি আপনার নির্দিষ্ট ডেটাসেটের দৈর্ঘ্য, প্রস্থ এবং স্পারসিটির উপর ভিত্তি করে পরিবর্তিত হতে পারে।

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))
)

18

Dplyr প্যাকেজ ব্যবহার করে আমরা নিম্নলিখিতভাবে NA ফিল্টার করতে পারি:

dplyr::filter(df,  !is.na(columnname))

1
এটি প্রায় 10.000 বারের চেয়ে ধীর সম্পাদন করেdrop_na()
21:48

17

এটি কমপক্ষে একটি নন-এনএ মান সহ সারিগুলি ফিরিয়ে দেবে।

final[rowSums(is.na(final))<length(final),]

এটি কমপক্ষে TWO নন-এনএ মানযুক্ত সারিগুলি ফিরিয়ে দেবে।

final[rowSums(is.na(final))<(length(final)-1),]

16

আপনার প্রথম প্রশ্নের জন্য, আমার কাছে একটি কোড রয়েছে যা আমি সমস্ত এনএ থেকে মুক্তি পেতে স্বাচ্ছন্দ্য বোধ করি। এটিকে আরও সহজ করার জন্য @ গ্রেগরকে ধন্যবাদ।

final[!(rowSums(is.na(final))),]

দ্বিতীয় প্রশ্নের জন্য, কোডটি পূর্ববর্তী সমাধান থেকে কেবলমাত্র একটি বিকল্প।

final[as.logical((rowSums(is.na(final))-5)),]

লক্ষ্য করুন -5 হ'ল আপনার ডেটাতে কলামের সংখ্যা। এটি সমস্ত এনএ সহ সারিগুলি সরিয়ে দেবে, যেহেতু সারি সুমস 5 টি যোগ করে এবং তারা বিয়োগের পরে জিরো হয়ে যায়। এইবার, as.logical প্রয়োজনীয়।


চূড়ান্ত [as.logical ((সারিসুমস (is.na (চূড়ান্ত))) - এনকোল (চূড়ান্ত)))] সর্বজনীন উত্তরের জন্য
ফেরোও

14

আমরা এটির জন্য সাবসেট ফাংশনটিও ব্যবহার করতে পারি।

finalData<-subset(data,!(is.na(data["mmul"]) | is.na(data["rnor"])))

এটি কেবলমাত্র সেই সারিগুলি দেবে যা মিমুল এবং rnor উভয় ক্ষেত্রেই এনএ নেই


9

আমি একটি সংশ্লেষী :)। এখানে আমি উত্তরগুলিকে একটি ফাংশনে সংযুক্ত করেছি:

#' 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)
}

8

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

7

একটা পদক্ষেপ উভয় সাধারণ এবং মোটামুটি পাঠযোগ্য কোড উৎপাদ ব্যবহার করা filterফাংশন এবং 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(.))

4
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এবং ?পরিবর্তন dart=c('NA')করার জন্য ফাংশন PARAM মধ্যেdart=c('NA', '?')


3

আমার ধারণা এটি আরও মার্জিতভাবে এইভাবে সমাধান করা যেতে পারে:

  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

6
এটি এর সাথে সারি ধরে রাখবে NA। আমি মনে করি ওপি যা চায় তা হ'ল:df %>% filter_all(all_vars(!is.na(.)))
asifzuba
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.