একটি আর ডেটা ফ্রেম থেকে `Inf` মানগুলি সাফ করা হচ্ছে


101

আর-তে, আমার একটি অপারেশন রয়েছে যা Infযখন আমি ডেটা ফ্রেমের রূপান্তর করি তখন কিছু মান তৈরি করে ।

আমি এই Infমানগুলিকে মানগুলিতে রূপান্তর করতে চাই NA। আমার কাছে কোডটি বড় ডেটার জন্য ধীর, এটি করার কোনও দ্রুত উপায় আছে?

বলুন আমার কাছে নিম্নলিখিত ডেটাফ্রেম রয়েছে:

dat <- data.frame(a=c(1, Inf), b=c(Inf, 3), d=c("a","b"))

নিম্নলিখিত একক ক্ষেত্রে কাজ করে:

 dat[,1][is.infinite(dat[,1])] = NA

সুতরাং আমি নিম্নলিখিত লুপ দিয়ে এটি সাধারণীকরণ

cf_DFinf2NA <- function(x)
{
    for (i in 1:ncol(x)){
          x[,i][is.infinite(x[,i])] = NA
    }
    return(x)
}

তবে আমি মনে করি না যে এটি সত্যিকার অর্থে আর এর শক্তি ব্যবহার করছে

উত্তর:


119

বিকল্প 1

data.frameএটিকে কলামগুলির তালিকা বলে সত্যটি ব্যবহার করুন , তারপরে এটিকে do.callপুনরায় তৈরি করতে ব্যবহার করুন data.frame

do.call(data.frame,lapply(DT, function(x) replace(x, is.infinite(x),NA)))

বিকল্প 2 - data.table

আপনি ব্যবহার করতে পারেন data.tableএবং set। এটি কিছু অভ্যন্তরীণ অনুলিপি এড়ানো হয়।

DT <- data.table(dat)
invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA)))

বা কলাম নম্বর ব্যবহার করে (খুব বেশি কলাম থাকলে সম্ভবত দ্রুত):

for (j in 1:ncol(DT)) set(DT, which(is.infinite(DT[[j]])), j, NA)

সময়

# some `big(ish)` data
dat <- data.frame(a = rep(c(1,Inf), 1e6), b = rep(c(Inf,2), 1e6), 
                  c = rep(c('a','b'),1e6),d = rep(c(1,Inf), 1e6),  
                  e = rep(c(Inf,2), 1e6))
# create data.table
library(data.table)
DT <- data.table(dat)

# replace (@mnel)
system.time(na_dat <- do.call(data.frame,lapply(dat, function(x) replace(x, is.infinite(x),NA))))
## user  system elapsed 
#  0.52    0.01    0.53 

# is.na (@dwin)
system.time(is.na(dat) <- sapply(dat, is.infinite))
# user  system elapsed 
# 32.96    0.07   33.12 

# modified is.na
system.time(is.na(dat) <- do.call(cbind,lapply(dat, is.infinite)))
#  user  system elapsed 
# 1.22    0.38    1.60 


# data.table (@mnel)
system.time(invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA))))
# user  system elapsed 
# 0.29    0.02    0.31 

data.tableদ্রুততম হয়। sapplyব্যবহারগুলি লক্ষণীয়ভাবে জিনিসগুলিকে ধীর করে দেয়।


1
সময় এবং পরিবর্তনসমূহ @ মিলনে দুর্দান্ত কাজ। আমি আশা করি অ্যাকাউন্টগুলিতে রেপ স্থানান্তর করার কোনও SO উপায় ছিল। আমি মনে করি আমি বাইরে যাব এবং আপনার কিছু অন্যান্য উত্তরকে সমর্থন করব।
আইআরটিএফএম

do.call এ ত্রুটি (ট্রেন, ল্যাপলি (ট্রেন, ফাংশন (এক্স)) প্রতিস্থাপন (x, is.infinite (এক্স)): 'কি' অবশ্যই একটি চরিত্রের স্ট্রিং বা একটি ফাংশন হতে হবে
হ্যাক-আর

60

ব্যবহার করুন sapplyএবংis.na<-

> dat <- data.frame(a=c(1, Inf), b=c(Inf, 3), d=c("a","b"))
> is.na(dat) <- sapply(dat, is.infinite)
> dat
   a  b d
1  1 NA a
2 NA  3 b

বা আপনি ব্যবহার করতে পারেন (@ মণেলকে ক্রেডিট প্রদান, যার সম্পাদনা এটি),

> is.na(dat) <- do.call(cbind,lapply(dat, is.infinite))

যা উল্লেখযোগ্যভাবে দ্রুত।


5
"কৌশল" বুঝতে পেরেছিল যে is.na<-কোনও ফলাফল গ্রহণ করবে না lapplyতবে সেটিকে গ্রহণ করবে sapply
আইআরটিএফএম

আমি কিছু সময় যুক্ত করেছি আমি নিশ্চিত নই কেন is.na<-সমাধানটি এত ধীর।
মলিন

কিছুটা প্রোফাইলিং, এবং আমি আপনার সমাধানটি আরও দ্রুত হতে সম্পাদনা করেছি।
মলিন

19

[<-এর mapplyচেয়ে কিছুটা দ্রুত sapply

> dat[mapply(is.infinite, dat)] <- NA

মিলের ডেটা সহ, সময়টি

> system.time(dat[mapply(is.infinite, dat)] <- NA)
#   user  system elapsed 
# 15.281   0.000  13.750 

11

এখানে Na_if () ফাংশনটি ব্যবহার করে একটি dplyr / tidyvers সমাধান দেওয়া হয়েছে :

dat %>% mutate_if(is.numeric, list(~na_if(., Inf)))

নোট করুন যে এটি কেবল এনএ দিয়ে ইতিবাচক অনন্ত প্রতিস্থাপন করে। নেতিবাচক অনন্ত মানগুলিও প্রতিস্থাপন করা দরকার হলে পুনরাবৃত্তি করা দরকার।

dat %>% mutate_if(is.numeric, list(~na_if(., Inf))) %>% 
  mutate_if(is.numeric, list(~na_if(., -Inf)))

5

হাবলার প্যাকেজে এই সমস্যার খুব সাধারণ সমাধান রয়েছে:

library(hablar)

dat %>% rationalize()

যা সমস্ত ইনফের সাথে ডেটা ফ্রেম ফেরত দেয় এনএতে রূপান্তরিত হয়।

উপরের কয়েকটি সমাধানের সাথে তুলনা করার সময়গুলি। কোড: গ্রন্থাগার (হাবলার) লাইব্রেরি (ডেটা টেবিল)

dat <- data.frame(a = rep(c(1,Inf), 1e6), b = rep(c(Inf,2), 1e6), 
                  c = rep(c('a','b'),1e6),d = rep(c(1,Inf), 1e6),  
                  e = rep(c(Inf,2), 1e6))
DT <- data.table(dat)

system.time(dat[mapply(is.infinite, dat)] <- NA)
system.time(dat[dat==Inf] <- NA)
system.time(invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA))))
system.time(rationalize(dat))

ফলাফল:

> system.time(dat[mapply(is.infinite, dat)] <- NA)
   user  system elapsed 
  0.125   0.039   0.164 
> system.time(dat[dat==Inf] <- NA)
   user  system elapsed 
  0.095   0.010   0.108 
> system.time(invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA))))
   user  system elapsed 
  0.065   0.002   0.067 
> system.time(rationalize(dat))
   user  system elapsed 
  0.058   0.014   0.072 
> 

ডেটা.ট্যাবল হাবলারের চেয়ে দ্রুত than তবে এর দীর্ঘতর বাক্য গঠন রয়েছে।


সময় দয়া করে?
রিচার্ডো

@ricardo কিছু সময় যুক্ত করেছে
davsjob

1

নেতিবাচক এবং ধনাত্মক অসম্পূর্ণতা পেতে ফেং মাইয়ের উপরে একটি পরিপাটি উত্তর রয়েছে:

dat %>% mutate_if(is.numeric, list(~na_if(., Inf))) %>% 
  mutate_if(is.numeric, list(~na_if(., -Inf)))

এটি কার্যকরভাবে কাজ করে, তবে একটি সতর্কতার শব্দটি অ্যাবস (।) এ পরিবর্তন করতে হবে না এটি একটি উক্ত মন্তব্যটিতে প্রস্তাবিত হিসাবে উভয় লাইন একবারে করতে হবে। এটি দেখতে যেমন কাজ করবে ঠিক তেমন দেখাবে, তবে ডেটাসেটের সমস্ত নেতিবাচক মানকে ধনাত্মক করে! আপনি এটি দিয়ে নিশ্চিত করতে পারেন:

data(iris)
#The last line here is bad - it converts all negative values to positive
iris %>% 
  mutate_if(is.numeric, ~scale(.)) %>%
  mutate(infinities = Sepal.Length / 0) %>%
  mutate_if(is.numeric, list(~na_if(abs(.), Inf)))

এক লাইনের জন্য, এটি কাজ করে:

  mutate_if(is.numeric, ~ifelse(abs(.) == Inf,NA,.))

1
ভালো বল ধরা! আমি আসল মন্তব্যে এটিকে প্রভাবিত করার জন্য একটি মন্তব্য যুক্ত করেছি - আমি মনে করি এটি একটি নতুন উত্তরের চেয়ে সমস্যা সমাধানের জন্য ভাল better এছাড়াও কোথাও মন্তব্য করার জন্য প্রয়োজনীয় 50 টি খ্যাতির কাছে আপনাকে কিছুটা কাছাকাছি পাওয়ার জন্য আপগের যোগ্য আপনার কয়েকটি পোস্ট পেয়েছে।
গ্রেগোর টমাস

ধন্যবাদ! হ্যাঁ আমি সক্ষম হলে একটি মন্তব্য করতে হবে।
মার্ক ই।

0

আরেকটি সমাধান:

    dat <- data.frame(a = rep(c(1,Inf), 1e6), b = rep(c(Inf,2), 1e6), 
                      c = rep(c('a','b'),1e6),d = rep(c(1,Inf), 1e6),  
                      e = rep(c(Inf,2), 1e6))
    system.time(dat[dat==Inf] <- NA)

#   user  system elapsed
#  0.316   0.024   0.340

MusTheDataGuy, আপনি আমার উত্তরটি সম্পাদনা করবেন তবে নিজের সমাধানটি যোগ করবেন না কেন? ইতিমধ্যে "অন্য উত্তর যুক্ত করুন" বোতামটি রয়েছে!
শিক্ষার্থী

-1

আপনি হ্যান্ডি রিপ্লেস_না ফাংশনটিও ব্যবহার করতে পারেন: https://tidyr.tidyverse.org/references/replace_na.html


1
এটি সীমান্তের লিংক-কেবল উত্তর । এখানে যত বেশি তথ্য অন্তর্ভুক্ত করতে আপনার উত্তরটি প্রসারিত করা উচিত, এবং কেবলমাত্র রেফারেন্সের জন্য লিঙ্কটি ব্যবহার করুন।
বিদায় স্ট্যাকএক্সচেঞ্জ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.