Data.frame හි ඇති සියලුම හෝ සමහර NAs (නැතිවූ අගයන්) සහිත පේළි ඉවත් කරන්න


876

මෙම දත්ත රාමුවේ ඇති රේඛා ඉවත් කිරීමට මම කැමතියි:

a) සියලුම තීරු හරහා s අඩංගු වේ 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

b) සමහර තීරු වල පමණක් s අඩංගුNA වන බැවින් මට මෙම ප්‍රති result ලය ලබා ගත හැකිය:

             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

Answers:


1079

එසේම පරීක්ෂා කරන්න 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සියල්ල ඉවත් කිරීම සඳහා වඩාත් සුදුසුය 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කිරීම වඩා පැහැදිලි හා වේගවත් ය.


8
පසුපස කොමාවෙහි ඇති වැදගත්කම final[complete.cases(final),]කුමක්ද?
hertzsprung

6
@hertzsprung ඔබට අවශ්‍ය වන්නේ පේළි මිස තීරු නොවේ. ඔබ එය කරන්නේ කෙසේද?
ජෝරිස් මේස්

4
පිළිබඳ සරල ප්‍රතික්ෂේප කිරීමක් complete.casesතිබේද? පේළි ඉවතලීම වෙනුවට NA සමඟ තබා ගැනීමට මට අවශ්‍ය නම්? final[ ! complete.cases(final),]සහයෝගය නොදක්වයි ...
කැලඹිලි_රූස්ටර්

2
finalදත්ත රාමු විචල්යද?
මෝර්ස්

1
ඇත්තෙන්ම ප්‍රතීක්.
ජෝරිස් මේස්

263

උත්සාහ කරන්න na.omit(your.data.frame). දෙවන ප්‍රශ්නය සඳහා, එය වෙනත් ප්‍රශ්නයක් ලෙස පළ කිරීමට උත්සාහ කරන්න (පැහැදිලි බව සඳහා).


na.omit පේළි පහත දැමූ නමුත් පේළි අංක ආරක්ෂා කරයි. නිසි ලෙස අංකනය කර ඇති පරිදි ඔබ මෙය නිවැරදි කරන්නේ කෙසේද?
වලස්

3
පේළි අංක ගැන ඔබ සැලකිලිමත් නොවන්නේ නම්, කරන්න rownames(x) <- NULL.
රෝමන් ලුස්ට්‍රික්

ඕනෑම තීරුවක na.omit()අඩංගු පේළි පහත වැටෙන බව කරුණාවෙන් සලකන්නNA
වික්ටර් මැක්ස්වෙල්

127

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

92

පේළි වල කිසියම් එන්ඒ එකක් තිබේදැයි පරීක්ෂා කිරීමට මම පහත ක්‍රමයට කැමැත්තෙමි:

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

මෙය පේළි වල කිසියම් NA එකක් තිබේද යන්න දැක්වෙන අගයන් සහිත තාර්කික දෛශිකය ලබා දෙයි. ඔබට පේළි කීයක් අතහැරිය යුතු දැයි බැලීමට ඔබට එය භාවිතා කළ හැකිය:

sum(row.has.na)

අවසානයේදී ඒවා අතහරින්න

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

NA වල යම් කොටසක් සමඟ පේළි පෙරීම සඳහා එය ටිකක් උපක්‍රමශීලී වේ (නිදසුනක් ලෙස, ඔබට 'අයදුම් කිරීමට' 'අවසාන [, 5: 6] පෝෂණය කළ හැකිය). පොදුවේ ගත් කල, ජෝරිස් මේස්ගේ විසඳුම වඩාත් අලංකාර බව පෙනේ.


2
මෙය අතිශයින් මන්දගාමී ය. උදා: ඉහත සඳහන් සම්පූර්ණ කේස් () විසඳුමට වඩා මන්දගාමී වේ. අවම වශයෙන්, මගේ නඩුවේ, xts දත්ත මත.
ඩේව්

3
rowSum(!is.na(final))වඩා සුදුසු යැයි පෙනේapply()
sindri_baldur

46

පේළි අවලංගු යැයි සලකන ආකාරය පිළිබඳ වැඩි පාලනයක් ඔබට අවශ්‍ය නම් තවත් විකල්පයක් වේ

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 යන පේළිය පමණක් ඉවත් කර ඇති අතර එය rnorAND යන දෙකම සඳහා NAs අඩංගු එකම පේළිය වේ cfam. නිශ්චිත අවශ්‍යතාවන්ට සරිලන පරිදි බූලියන් තර්කනය වෙනස් කළ හැකිය.


6
නමුත් ඔබට තීරු බොහොමයක් පරීක්ෂා කිරීමට අවශ්‍ය නම්, එක් එක් යතුරු ලියනය නොකර, ඔබට අවසාන පරාසය [, 4: 100] භාවිතා කළ හැක්කේ කෙසේද?
හර්මන් ටූට්‍රොට්

41

එක් එක් පේළිය සඳහා වලංගු NA ගණන කොපමණ දැයි පාලනය කිරීමට ඔබට අවශ්‍ය නම්, මෙම ක්‍රියාව උත්සාහ කරන්න. බොහෝ සමීක්ෂණ දත්ත කට්ටල සඳහා, බොහෝ හිස් ප්‍රශ්න ප්‍රතිචාර මඟින් ප්‍රති .ල විනාශ කළ හැකිය. එබැවින් ඒවා යම් සීමාවකට පසු මකා දමනු ලැබේ. මෙම ක්‍රියාව මඟින් පේළිය මකා දැමීමට පෙර කොපමණ එන්.ඒ. ප්‍රමාණයක් තිබිය යුතුද යන්න තෝරා ගැනීමට ඔබට ඉඩ සලසයි:

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

පෙරනිමියෙන්, එය සියලු NAs ඉවත් කරනු ඇත:

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

39

කාර්ය සාධනය ප්‍රමුඛතාවයක් නම්, භාවිතා කරන්න data.tableසහ na.omit()විකල්ප පරාමිතිය සමඟ cols=.

na.omit.data.table මගේ මිණුම් ලකුණෙහි වේගවත්ම වේ (පහත බලන්න), සියලු තීරු සඳහා හෝ තෝරාගත් තීරු සඳහා වේවා (OP ප්‍රශ්න 2 කොටස).

ඔබට භාවිතා කිරීමට අවශ්‍ය නැතිනම් භාවිතා data.tableකරන්නcomplete.cases() .

වැනිලා මත data.frame, complete.casesවඩා වේගවත් na.omit()හෝ dplyr::drop_na(). na.omit.data.frameසහාය නොදක්වන බව සැලකිල්ලට ගන්නcols= .

මිණුම් දණ්ඩේ ප්‍රති result ලය

මෙන්න පාදම (නිල්), dplyr(රෝස) සහdata.table , අතුරුදහන් වීම ස්වාධීන 5% සම්භාවිතාව සමඟ සංඛ්යාත්මක විචල්යයන් 20 ක් 1 නිරීක්ෂණ වඳුරාගේ දත්ත සමුදාය, සහ මත (කහ) එක්කෝ සියලු තහංචි ඉවත් කර හෝ අස්ථානගතවී නිරීක්ෂණ තෝරා සඳහා ක්රම 2 වන කොටස සඳහා විචල්යයන් 4 ක උප කුලකයක්.

ඔබගේ විශේෂිත දත්ත කට්ටලයේ දිග, පළල සහ විරලභාවය මත පදනම්ව ඔබේ ප්‍රති results ල වෙනස් විය හැකිය.

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

19

Dplyr පැකේජය භාවිතා කර අපට පහත පරිදි NA පෙරණය කළ හැකිය:

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

2
මෙය 10.000 ගුණයකින් මන්දගාමී වේdrop_na()
සිමානෝ

Im සිමානෝ සමහර විට සත්‍ය විය හැකි නමුත් බහු විචල්‍යයන් drop_na සඳහා “ඕනෑම” තර්කනයක් filterභාවිතා කරන අතර “සියල්ල” තර්කනය භාවිතා කරයි. එබැවින් ඔබට ප්‍රකාශනයේ වැඩි නම්යතාවයක් අවශ්‍ය නම්, පෙරනයට වැඩි හැකියාවන් ඇත.
ජිගුන්ජර්

ig ජිග්ගුන්ජර් එය ඇත්තෙන්ම සත්‍යයකි! එය සැබවින්ම රඳා පවතින්නේ ඔබ සාක්ෂාත් කර ගැනීමට උත්සාහ කරන දේ මත ය :)
සිමානෝ

17

මෙය අවම වශයෙන් එක් NA නොවන අගයක් ඇති පේළි නැවත ලබා දෙනු ඇත.

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

මෙය අවම වශයෙන් TWO NA නොවන අගයක් ඇති පේළි නැවත ලබා දෙනු ඇත.

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

17

ඔබගේ පළමු ප්‍රශ්නය සඳහා, සියලු NA වලින් මිදීමට මට පහසු කේතයක් මා සතුව ඇත. එය සරල කිරීමට @ ග්‍රෙගර්ට ස්තූතියි.

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

දෙවන ප්‍රශ්නය සඳහා, කේතය පෙර විසඳුමෙන් විකල්පයක් පමණි.

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

-5 යනු ඔබේ දත්තවල ඇති තීරු ගණන බව සලකන්න. පේළි සෑම් 5 ක් එකතු කරන අතර අඩු කිරීමෙන් පසු ඒවා ශුන්‍ය බවට පත්වන බැවින් මෙය සියලු එන්ඒ සමඟ පේළි ඉවත් කරයි. මෙවර, as.logical අවශ්‍ය වේ.


අවසන් [as.logical ((rowSums (is.na (අවසන්)) - ncol (අවසන්))),] විශ්ව පිළිතුර සඳහා
Ferroao

14

මේ සඳහා අපට උප කුලක ශ්‍රිතය ද භාවිතා කළ හැකිය.

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

මෙය ලබා දෙන්නේ mmul සහ rnor යන දෙකෙහිම NA නොමැති පේළි පමණි


11

සාමාන්‍යයෙන් කියවිය හැකි කේතයක් ලබා දෙන එක් ප්‍රවේශයක් නම් function dplyr} පැකේජයෙන් filter()ශ්‍රිතය සහ across()සහායක කාර්යයන් භාවිතා කිරීමයි.

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

භාවිතා කරමින් තවත් උදාහරණයක් සඳහා මෙහි බලන්නacross
jiggunjer

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ඔබේ දත්ත රාමුව ලෙස උපකල්පනය කිරීමෙන් අපේක්ෂිත ප්‍රති output ලය ලබා ගත හැකිය

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

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' ඇති දත්ත රාමුවෙන් සියලුම පේළි මකා දමා ප්‍රති data ල දත්ත ලබා දෙයි. ඔබ වැනි බහු අගයයන් සඳහා පරීක්ෂා කිරීමට අවශ්ය නම් NAහා ?වෙනස් dart=c('NA')කිරීමට කාර්යය param දීdart=c('NA', '?')


2

මගේ අනුමානය නම් මෙය මේ ආකාරයෙන් වඩාත් අලංකාර ලෙස විසඳා ගත හැකි බවයි:

  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

9
මෙය පේළි රඳවා ගනී NA. මම හිතන්නේ OP ට අවශ්‍ය දේ:df %>% filter_all(all_vars(!is.na(.)))
asifzuba
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.