সুনির্দিষ্ট সারিগুলিতে কন্ডিশনার করার সময় একাধিক কলামকে গতিশীল রূপে পরিবর্তন করা


11

আমি জানি এখানে প্রায় একই ধরণের প্রশ্ন রয়েছে, তবে এর মধ্যে কোনওটিই আমার কাছে সঠিক সমস্যার সমাধান করছে বলে মনে হয় না।

set.seed(4)
df = data.frame(
  Key = c("A", "B", "A", "D", "A"),
  Val1 = rnorm(5),
  Val2 = runif(5),
  Val3 = 1:5
)

আমি সারিগুলির জন্য কলামের মান কলামগুলির মান শূন্য করতে চাই যেখানে কী == "এ" কলামের নামগুলি একটি এর মাধ্যমে উল্লেখ করা হয়েছে grep:

cols = grep("Val", names(df), value = TRUE)

সাধারণত আমি এই ক্ষেত্রে যা চাই তা অর্জন করতে আমি এটি এর data.tableমতো ব্যবহার করব :

library(data.table)
df = as.data.table(df)
df[Key == "A", (cols) := 0]

এবং পছন্দসই আউটপুটটি এরকম:

  Key      Val1       Val2 Val3
1   A  0.000000 0.00000000    0
2   B -1.383814 0.55925762    2
3   A  0.000000 0.00000000    0
4   D  1.437151 0.05632773    4
5   A  0.000000 0.00000000    0

যাইহোক এবার আমি dplyrযেমন টিম প্রজেক্টে কাজ করছি যেখানে সবাই এটি ব্যবহার করে তাই আমাকে ব্যবহার করা দরকার। আমি সবেমাত্র ডেটা সরবরাহ করেছি তা বর্ণনামূলক এবং আমার আসল ডেটাটি হল> 5 মান সারি 16 মান কলাম আপডেট করা। আমি যে সমাধান করতে পারলাম কেবল সেগুলিই mutate_atএরকম ব্যবহার করে :

df %>% mutate_at(.vars = vars(cols), .funs = function(x) ifelse(df$Key == "A", 0, x))

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

আমি অনেকগুলি সংমিশ্রণগুলি ব্যবহার করে map, অকেজো ব্যবহার করে !!, ব্যবহার করে getএবং :=(যা বিরক্তিকরভাবে :=ডেটা.টিটেবলের মধ্যে মুখোশ পেতে পারে ) ইত্যাদি ব্যবহার করে চেষ্টা করেছি , তবে আমি মনে করি যে এই কাজটি কীভাবে বৈধ সমাধান তৈরি করার পক্ষে যথেষ্ট গভীর নয় of


6
এটি কত সময় নেয়? df প্রয়োগ [df প্রয়োগ $ কী == "একজন", COLS] <- 0। আমি দেখতে পাচ্ছি যে এটি ধীর গতির কারণ আপনি কল করছেন এবং কলাম এবং সারিগুলিতে লুপিং করছেন el
বোকা ওল্ফ

বোকা ওল্ফ, খুব কমপ্যাক্ট এবং মার্জিত হওয়ার সময় এটি আমার ডেটাগুলির সাথে আসলে খুব দ্রুত। ধন্যবাদ। আপনি যদি চান তবে একটি উত্তর হিসাবে এটিকে নির্দ্বিধায় যোগ করুন।
LiviusI

ঠিক আছে আমি এর আশেপাশে যাওয়ার আরও একটি সমাধান আপনাকে দেখাতে পারি ..
বোকা ওল্ফ

উত্তর:


9

এই dplyr কমান্ড সহ,

df %>% mutate_at(.vars = vars(cols), .funs = function(x) ifelse(df$Key == "A", 0, x))

আপনি আসলে df $ কী == "এ", n বারের বিবৃতিটি মূল্যায়ন করছেন, যেখানে n = আপনার কলামগুলির সংখ্যা।

চারপাশের একটি কাজ হ'ল আপনি যে সারিগুলি পরিবর্তন করতে চান তা পূর্বনির্ধারণ করা:

idx = which(DF$Key=="A")
DF %>% mutate_at(.vars = vars(cols), .funs = function(x){x[idx]=0;x})

@CCCTTcan দ্বারা সঠিকভাবে নির্দেশিত একটি পরিষ্কার এবং সর্বোত্তম উপায় (নীচে মন্তব্যগুলি দেখুন), অতিরিক্ত পরামিতিগুলি পাস করার সময় ফাংশনটি প্রতিস্থাপনটি ব্যবহার করা হবে:

DF %>% mutate_at(.vars = vars(cols), replace, DF$Key == 'A', 0)

আমরা পরীক্ষার জন্য এই সমস্ত পন্থা রাখতে পারি এবং আমি মনে করি dplyr এবং ডেটা টেবিল তুলনীয়।

#simulate data
set.seed(100)
Key = sample(LETTERS[1:3],1000000,replace=TRUE)
DF = as.data.frame(data.frame(Key,matrix(runif(1000000*10),nrow=1000000,ncol=10)))
DT = as.data.table(DF)

cols = grep("[35789]", names(DF), value = TRUE)

#long method
system.time(DF %>% mutate_at(.vars = vars(cols), .funs = function(x) ifelse(DF$Key == "A", 0, x)))
user  system elapsed 
  0.121   0.035   0.156 

#old base R way
system.time(DF[idx,cols] <- 0)
   user  system elapsed 
  0.085   0.021   0.106 

#dplyr
# define function
func = function(){
       idx = which(DF$Key=="A")
       DF %>% mutate_at(.vars = vars(cols), .funs = function(x){x[idx]=0;x})
}
system.time(func())
user  system elapsed 
  0.020   0.006   0.026

#data.table
system.time(DT[Key=="A", (cols) := 0])
   user  system elapsed 
  0.012   0.001   0.013 
#replace with dplyr
system.time(DF %>% mutate_at(.vars = vars(cols), replace, DF$Key == 'A', 0))
user  system elapsed 
  0.007   0.001   0.008

4
মিউটেটের অতিরিক্ত যুক্তিগুলি একবার মূল্যায়ন করা হয় এবং প্রদত্ত ফাংশনের প্যারামিটার হিসাবে পাস করা হয় (উদাহরণস্বরূপ ল্যাপলির অনুরূপ), সুতরাং আপনি স্পষ্টভাবে টেম্পে ভেরিয়েবল আইডএক্স তৈরি না করে এটি করতে পারেনdf %>% mutate_at(vars(contains('Val')), replace, df$Key == 'A', 0)
আইসক্রিমটউকেন

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

আমার মেশিনে পরীক্ষা করার পরে, মনে হচ্ছে replaceপদ্ধতিটি আপনার আসল idxপদ্ধতির চেয়ে কিছুটা ধীর ।
আইসক্রিমটোকন

1
এছাড়াও আমি মনে করি dplyr::if_else()বেসের চেয়ে দ্রুত ifelse()
সিন্ড্রি_বালদুর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.