সমস্ত মানগুলি NA যেখানে ডেটাফ্রেম থেকে কলামগুলি সরান


149

আমি একটি ডেটা ফ্রেমে সমস্যায় পড়ছি এবং সত্যিই নিজেই
এই সমস্যাটি সমাধান করতে পারছি না: ডেটাফ্রেমের কলাম হিসাবে নির্বিচারে বৈশিষ্ট্য রয়েছে এবং প্রতিটি সারি একটি ডেটা সেট উপস্থাপন করে

প্রশ্নটি হল: সমস্ত সারিগুলির মান এনএ যেখানে কলামগুলি
থেকে কীভাবে মুক্তি পাবেন ?

উত্তর:


155

এটা চেষ্টা কর:

df <- df[,colSums(is.na(df))<nrow(df)]

3
এটি একটি বস্তুকে পুরানো অবজেক্টের আকার তৈরি করে যা বড় বস্তুগুলির মেমরির সমস্যা। আকার হ্রাস করতে একটি ফাংশন ব্যবহার করা ভাল। ফিল্টার ব্যবহার করে বা ডেটা.ট্যাবল ব্যবহার করে উত্তর বেলো আপনার স্মৃতি ব্যবহারে সহায়তা করবে।
মেটলেশা

3
এটি অ-সংখ্যাযুক্ত কলামগুলির সাথে কাজ করে বলে মনে হয় না।
verbamour

এটি
কপির

97

প্রস্তাবিত দুটি পন্থাগুলি তাদের তৈরি বড় মাপের ডেটা সেটগুলির সাথে ব্যর্থ হয়েছে (অন্যান্য মেমরি সমস্যার মধ্যে রয়েছে) is.na(df)যা কোনও আকারের আকার হিসাবে হবে df

এখানে দুটি পন্থা যা বেশি স্মৃতি এবং সময় দক্ষ

একটি পদ্ধতির ব্যবহার Filter

Filter(function(x)!all(is.na(x)), df)

এবং ডেটা টেবিল ব্যবহার করে একটি পদ্ধতির (সাধারণ সময় এবং মেমরির দক্ষতার জন্য)

library(data.table)
DT <- as.data.table(df)
DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]

বড় ডেটা ব্যবহার করে উদাহরণ (30 কলাম, 1e6 সারি)

big_data <- replicate(10, data.frame(rep(NA, 1e6), sample(c(1:8,NA),1e6,T), sample(250,1e6,T)),simplify=F)
bd <- do.call(data.frame,big_data)
names(bd) <- paste0('X',seq_len(30))
DT <- as.data.table(bd)

system.time({df1 <- bd[,colSums(is.na(bd) < nrow(bd))]})
# error -- can't allocate vector of size ...
system.time({df2 <- bd[, !apply(is.na(bd), 2, all)]})
# error -- can't allocate vector of size ...
system.time({df3 <- Filter(function(x)!all(is.na(x)), bd)})
## user  system elapsed 
## 0.26    0.03    0.29 
system.time({DT1 <- DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]})
## user  system elapsed 
## 0.14    0.03    0.18 

6
খুব সুন্দর. data.frameযদিও আপনি একই সঙ্গে করতে পারে । এখানে আসলে কিছুই প্রয়োজন নেই data.table। মূলটি হ'ল lapply, যা দ্বারা করা সম্পূর্ণ সামগ্রীর অনুলিপি এড়িয়ে চলে is.na(df)। এটি নির্দেশ করার জন্য +10।
ম্যাট ডাউলে

1
আপনি এটি একটি ডেটা.ফ্রেম দিয়ে কীভাবে করবেন? @ ম্যাট-ডোল
এস_এ

8
@ এস_এ, bd1 <- bd[, unlist(lapply(bd, function(x), !all(is.na(x))))]
গর্ত

6
@ মিলেল আমার মনে হয় আপনার ,পরে অপসারণ করা দরকার function(x)- বিটিডব্লিউ উদাহরণের জন্য ধন্যবাদ
থিম হেনিস

1
আপনি কি এটি দিয়ে: = বা একটি সেট () দিয়ে দ্রুত করতে পারবেন?
স্ক্যান

49

dplyrএখন এখানে একটি select_ifক্রিয়া রয়েছে যা এখানে সহায়ক হতে পারে:

library(dplyr)
temp <- data.frame(x = 1:5, y = c(1,2,NA,4, 5), z = rep(NA, 5))
not_all_na <- function(x) any(!is.na(x))
not_any_na <- function(x) all(!is.na(x))

> temp
  x  y  z
1 1  1 NA
2 2  2 NA
3 3 NA NA
4 4  4 NA
5 5  5 NA

> temp %>% select_if(not_all_na)
  x  y
1 1  1
2 2  2
3 3 NA
4 4  4
5 5  5

> temp %>% select_if(not_any_na)
  x
1 1
2 2
3 3
4 4
5 5

dplyrসমাধান খুঁজছেন এখানে এসেছেন । হতাশ ছিল না। ধন্যবাদ!
অ্যান্ড্রু ব্রাজা 16

আমি এটিতে এই সমস্যাটি পেয়েছি যে এটি বেশিরভাগের সাথে ভেরিয়েবলগুলি মুছে ফেলবে তবে সমস্ত মান অনুপস্থিত নয়
এমবির্গ

15

অন্য উপায় হ'ল apply()ফাংশনটি ব্যবহার করা ।

আপনার যদি ডেটা.ফ্রেম থাকে

df <- data.frame (var1 = c(1:7,NA),
                  var2 = c(1,2,1,3,4,NA,NA,9),
                  var3 = c(NA)
                  )

তারপরে আপনি apply()কোন কলামগুলি আপনার শর্ত পূরণ করে তা দেখতে ব্যবহার করতে পারেন এবং সুতরাং আপনি কেবলমাত্র একটি applyপদ্ধতির সাহায্যে মুসার উত্তরের মতো একই সাবসেটিংটি করতে পারেন ।

> !apply (is.na(df), 2, all)
 var1  var2  var3 
 TRUE  TRUE FALSE 

> df[, !apply(is.na(df), 2, all)]
  var1 var2
1    1    1
2    2    2
3    3    1
4    4    3
5    5    4
6    6   NA
7    7   NA
8   NA    9

3
আমি আশা করেছি এটি দ্রুত হবে, কারণ কলসাম () সমাধানটি আরও কাজ করছে বলে মনে হচ্ছে। তবে আমার পরীক্ষার সেটটিতে (এর আগে 2114 ওভারের 1614 ভেরিয়েবল, পরে 1377 ভেরিয়েবল) পরে ঠিক 3 গুণ বেশি সময় লাগে। (তবে একটি আকর্ষণীয় পদ্ধতির জন্য +1))
ড্যারেন কুক

10

খেলায় দেরি হলেও আপনি janitorপ্যাকেজটিও ব্যবহার করতে পারেন । এই ফাংশনটি সমস্ত এনএ হ'ল কলামগুলি সরিয়ে ফেলবে এবং সমস্ত এনএর মতো সারিগুলি সরাতেও এটি পরিবর্তন করা যেতে পারে।

df <- janitor::remove_empty(df, which = "cols")



4

গৃহীত উত্তরটি সংখ্যাযুক্ত কলামগুলির সাথে কাজ করে না। এই উত্তর থেকে , নিম্নলিখিত বিভিন্ন ধরণের ডেটাযুক্ত কলামগুলির সাথে কাজ করে

Filter(function(x) !all(is.na(x)), df)

আপনার আগে ৪ বছর আগে এই থ্রেডে অন্য কেউ ইতিমধ্যে একই উত্তর পোস্ট করেছেন ... নীচে গলির উত্তর দেখুন।
এন্ড্রেবি.বি

2

purrrপ্যাকেজ সহ আরও একটি বিকল্প :

library(dplyr)

df <- data.frame(a = NA,
                 b = seq(1:5), 
                 c = c(rep(1, 4), NA))

df %>% purrr::discard(~all(is.na(.)))
df %>% purrr::keep(~!all(is.na(.)))

1

আমি আশা করি এটিও সাহায্য করতে পারে। এটি একটি একক কমান্ডে তৈরি করা যেতে পারে তবে এটি দুটি কমান্ডে ভাগ করে আমার পড়া সহজ হয়েছে। আমি নিম্নলিখিত নির্দেশাবলী সঙ্গে একটি ফাংশন তৈরি এবং দ্রুত বাজ কাজ।

naColsRemoval = function (DataTable) { na.cols = DataTable [ , .( which ( apply ( is.na ( .SD ) , 2 , all ) ) )] DataTable [ , unlist (na.cols) := NULL , with = F] }

.এসডি আপনার ইচ্ছামত, টেবিলের অংশে যাচাইকরণ সীমাবদ্ধ করার অনুমতি দেবে, তবে এটি পুরো টেবিলটিকে গ্রহণ করবে


1

একটি সহজ base Rবিকল্প হতে পারে colMeans():

df[, colMeans(is.na(df)) != 1]

0

আপনি জ্যানিটর প্যাকেজটি ব্যবহার করতে পারেন remove_empty

library(janitor)

df %>%
  remove_empty(c("rows", "cols")) #select either row or cols or both

এছাড়াও, আরেকটি dplyr পদ্ধতির

 library(dplyr) 
 df %>% select_if(~all(!is.na(.)))

অথবা

df %>% select_if(colSums(!is.na(.)) == nrow(df))

যদি আপনি কেবলমাত্র অনুপস্থিত মানের উদাহরণ সহ কলামটি বাদ / রাখতে চান তবে এটিও কার্যকর

 df %>% select_if(colSums(!is.na(.))>500)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.