dplyr পরিবর্তন / সারিগুলির একটি উপসেটে বেশ কয়েকটি কলাম প্রতিস্থাপন করুন


86

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

library(data.table)

# Create some sample data
set.seed(1)
dt <- data.table(site = sample(1:6, 50, replace=T),
                 space = sample(1:4, 50, replace=T),
                 measure = sample(c('cfl', 'led', 'linear', 'exit'), 50, 
                               replace=T),
                 qty = round(runif(50) * 30),
                 qty.exit = 0,
                 delta.watts = sample(10.5:100.5, 50, replace=T),
                 cf = runif(50))

# Replace the values of several columns for rows where measure is "exit"
dt <- dt[measure == 'exit', 
         `:=`(qty.exit = qty,
              cf = 0,
              delta.watts = 13)]

এই একই সমস্যার একটি সাধারণ dplyr সমাধান আছে? আমি ifelse ব্যবহার এড়াতে চাই কারণ আমি একাধিকবার শর্তটি টাইপ করতে চাই না - এটি একটি সরল উদাহরণ, তবে কখনও কখনও একক শর্তের উপর ভিত্তি করে অনেকগুলি অ্যাসাইনমেন্ট থাকে।

সাহায্যের জন্য আগাম ধন্যবাদ!

উত্তর:


83

এই সমাধানগুলি (1) পাইপলাইন বজায় রাখে, (2) তা করে না ইনপুটটি ওভাররাইট করে এবং (3) কেবল একবার শর্তটি নির্দিষ্ট করা দরকার:

1a) mutate_cond পাইপলাইনে অন্তর্ভুক্ত করা যেতে পারে এমন ডেটা ফ্রেম বা ডেটা টেবিলগুলির জন্য একটি সাধারণ ফাংশন তৈরি করুন। এই ফাংশনটি এর মতো mutateতবে শর্তটি সন্তুষ্ট করে কেবল সারিগুলিতে কাজ করে:

mutate_cond <- function(.data, condition, ..., envir = parent.frame()) {
  condition <- eval(substitute(condition), .data, envir)
  .data[condition, ] <- .data[condition, ] %>% mutate(...)
  .data
}

DF %>% mutate_cond(measure == 'exit', qty.exit = qty, cf = 0, delta.watts = 13)

1 বি) mutate_last এটি আবার ডেটা ফ্রেম বা ডেটা টেবিলগুলির জন্য একটি বিকল্প ফাংশন যা আবার এর মতো mutateতবে কেবলমাত্র group_by(নীচের উদাহরণ হিসাবে) এর মধ্যে ব্যবহৃত হয় এবং প্রতিটি গ্রুপের পরিবর্তে কেবলমাত্র শেষ গ্রুপে কাজ করে। নোট করুন যে সত্য> মিথ্যা তাই যদি group_byকোনও শর্ত নির্দিষ্ট করে তবে mutate_lastকেবল সেই শর্তটি সন্তুষ্ট করে সারিগুলিতে কাজ করবে।

mutate_last <- function(.data, ...) {
  n <- n_groups(.data)
  indices <- attr(.data, "indices")[[n]] + 1
  .data[indices, ] <- .data[indices, ] %>% mutate(...)
  .data
}


DF %>% 
   group_by(is.exit = measure == 'exit') %>%
   mutate_last(qty.exit = qty, cf = 0, delta.watts = 13) %>%
   ungroup() %>%
   select(-is.exit)

2) ফ্যাক্টর আউট শর্ত ফ্যাক্টর এটি একটি অতিরিক্ত কলাম তৈরি করে শর্তটি আউট করে যা পরে সরিয়ে ফেলা হয়। তারপর ব্যবহার ifelse, replaceবা গাণিতিক logicals মত সচিত্র। এটি ডেটা টেবিলগুলির জন্যও কাজ করে।

library(dplyr)

DF %>% mutate(is.exit = measure == 'exit',
              qty.exit = ifelse(is.exit, qty, qty.exit),
              cf = (!is.exit) * cf,
              delta.watts = replace(delta.watts, is.exit, 13)) %>%
       select(-is.exit)

3) sqldf আমরা updateডেটা ফ্রেমগুলির জন্য পাইপলাইনে স্কুয়েলডিএফ প্যাকেজটির মাধ্যমে এসকিউএল ব্যবহার করতে পারি (তবে ডেটা টেবিলগুলি না রূপান্তর না করা - এটি ডিপি্লায়ারে একটি বাগ উপস্থাপন করতে পারে d dplyr সংখ্যা 1579 দেখুন )। মনে হতে পারে যে অস্তিত্বের কারণে আমরা এই কোডের ইনপুটটি updateঅনস্বীকার্যভাবে পরিবর্তন করছি তবে প্রকৃতপক্ষে updateএটি অস্থায়ীভাবে উত্পন্ন ডাটাবেসে ইনপুটটির অনুলিপিটিতে কাজ করছে এবং প্রকৃত ইনপুটটিতে নয়।

library(sqldf)

DF %>% 
   do(sqldf(c("update '.' 
                 set 'qty.exit' = qty, cf = 0, 'delta.watts' = 13 
                 where measure = 'exit'", 
              "select * from '.'")))

৪) সারি_আর_সামান্য একটি ফেরত দেওয়ার ক্ষেত্রে row_case_whenসংজ্ঞায়িত করে দেখুন : কেস_ওয়েন দিয়ে কীভাবে ভেক্টরাইজ করবেন? । এটি অনুরূপ সিনট্যাক্স ব্যবহার করে case_whenতবে সারিগুলিতে প্রযোজ্য।

library(dplyr)

DF %>%
  row_case_when(
    measure == "exit" ~ data.frame(qty.exit = qty, cf = 0, delta.watts = 13),
    TRUE ~ data.frame(qty.exit, cf, delta.watts)
  )

নোট 1: আমরা এটি হিসাবে ব্যবহার করেছিDF

set.seed(1)
DF <- data.frame(site = sample(1:6, 50, replace=T),
                 space = sample(1:4, 50, replace=T),
                 measure = sample(c('cfl', 'led', 'linear', 'exit'), 50, 
                               replace=T),
                 qty = round(runif(50) * 30),
                 qty.exit = 0,
                 delta.watts = sample(10.5:100.5, 50, replace=T),
                 cf = runif(50))

নোট 2: কত সহজে সারির একটি উপসেট আপডেট উল্লেখ করার সমস্যা এছাড়াও dplyr বিষয়ে আলোচনা করা হয় 134 , 631 , 1518 এবং 1573 সঙ্গে 631 মূল থ্রেড হচ্ছে এবং 1573 উত্তর এখানে একটি পর্যালোচনা হচ্ছে।


4
দুর্দান্ত উত্তর, ধন্যবাদ! আপনার মিউট্যাট_কন্ড এবং @ কেভিন উশির পরিবর্তিত_যখন উভয়ই এই সমস্যার ভাল সমাধান। আমি মনে করি আমার পঠনযোগ্যতা / পরিবর্তনের নমনীয়তার জন্য কিছুটা অগ্রাধিকার রয়েছে, তবে আমি এই উত্তরটির পুরোপুরি "চেক" দেব।
ক্রিস নিউটন

আমি সত্যিই mutate_cond পদ্ধতির পছন্দ করি। এটি আমার কাছে খুব বেশি মনে হয় এই ফাংশন বা এর খুব কাছাকাছি কিছুতে ডিসপ্লায়ার অন্তর্ভুক্তির যোগ্যতা রয়েছে এবং লোকেদের যে ব্যবহারের ক্ষেত্রে বিবেচনা করা হচ্ছে তার জন্য ভেক্টরাইজড সুইচ (এটি github.com/hadley/dplyr/issues/1573 তে আলোচনা করা হয়েছে ) এর চেয়ে ভাল সমাধান হবে would সম্পর্কে এখানে ...
ম্যাগনাস

আমি mutate_cond পছন্দ করি। বিভিন্ন বিকল্পের পৃথক উত্তর হওয়া উচিত।
হোলার ব্র্যান্ডেল

এটি কয়েক বছর হয়ে গেছে এবং গিথুব সমস্যাগুলি বন্ধ এবং লক করা আছে বলে মনে হচ্ছে। এই সমস্যার কোনও সরকারী সমাধান আছে কি?
স্থির_আরত্তি

27

আপনি এটি magrittrদ্বিমুখী পাইপ দিয়ে করতে পারেন %<>%:

library(dplyr)
library(magrittr)

dt[dt$measure=="exit",] %<>% mutate(qty.exit = qty,
                                    cf = 0,  
                                    delta.watts = 13)

এটি টাইপিংয়ের পরিমাণ হ্রাস করে, তবে এটির তুলনায় এখনও অনেক ধীর data.table


প্রকৃতপক্ষে, এখন আমি এটি পরীক্ষা করার সুযোগ পেয়েছি, আমি এমন একটি সমাধান পছন্দ করবো যা ডিটি [dt $ پیمার == 'প্রস্থান',] স্বরলিপি ব্যবহার করে সাবসেট করার প্রয়োজনীয়তা এড়ায়, যেহেতু এটি দীর্ঘকাল ধরে অনর্থক হতে পারে dt নাম।
ক্রিস নিউটন

কেবল একটি এফওয়াইআই, তবে এই সমাধানটি কেবল তখনই কাজ করবে যদি data.frame/tibble ইতিমধ্যে সংজ্ঞায়িত কলামটি থাকে mutate। আপনি যদি কোনও নতুন কলাম যুক্ত করার চেষ্টা করছেন তবে এটি কাজ করবে না, উদাহরণস্বরূপ, প্রথমবার লুপের মধ্য দিয়ে দৌড়তে এবং একটিতে পরিবর্তন করা data.frame
উরসুস ফ্রস্ট

@ উরুসফ্রস্ট নতুন কলাম যুক্ত করা যা ডেটাসেটের কেবলমাত্র একটি উপসেটই আমার কাছে অদ্ভুত বলে মনে হয়। আপনি যে সারিতে সাবসেট করা নেই তাতে এনএ যুক্ত করবেন?
বড়ালিউহ

@ বরালিউহ হ্যাঁ, আমি এটির প্রশংসা করতে পারি। এটি এমন লুপের অংশ যেখানে আমি তারিখের তালিকার উপরে ডেটা বৃদ্ধি এবং সংযোজন করি। প্রথম কয়েকটি তারিখগুলি পরবর্তী তারিখের চেয়ে আলাদাভাবে আচরণ করতে হবে কারণ এটি রিয়েল-ওয়ার্ল্ড ব্যবসায়িক প্রক্রিয়াগুলির প্রতিরূপ করছে। আরও পুনরাবৃত্তিতে, তারিখের শর্তের উপর নির্ভর করে ডেটা আলাদাভাবে গণনা করা হয়। শর্তসাপেক্ষতার কারণে, আমি অজান্তে এর আগের তারিখগুলি পরিবর্তন করতে চাই নাdata.frame । এফডাব্লুআইডাব্লু, আমি কেবল data.tableপরিবর্তে ব্যবহার করতে ফিরে গিয়েছিলাম dplyrকারণ এর iপ্রকাশটি সহজেই এটি পরিচালনা করে - প্লাস্টিকের লুপটি আরও দ্রুত চলে।
উরসুস ফ্রস্ট

19

এখানে আমার পছন্দ মতো একটি সমাধান রয়েছে:

mutate_when <- function(data, ...) {
  dots <- eval(substitute(alist(...)))
  for (i in seq(1, length(dots), by = 2)) {
    condition <- eval(dots[[i]], envir = data)
    mutations <- eval(dots[[i + 1]], envir = data[condition, , drop = FALSE])
    data[condition, names(mutations)] <- mutations
  }
  data
}

এটি আপনাকে উদাহরণস্বরূপ জিনিস লিখতে দেয়

mtcars %>% mutate_when(
  mpg > 22,    list(cyl = 100),
  disp == 160, list(cyl = 200)
)

যা বেশ পঠনযোগ্য - যদিও এটি যতটা পারফরম্যান্ট হতে পারে তেমন নাও হতে পারে।


14

উপরের আইপি 10 হিসাবে দেখানো হয়েছে, ডিপিপ্লায়ারে সাবসেট রিপ্লেসমেন্ট করার সহজ উপায় নেই কারণ ডিটি পাস-বাই-ভ্যালু ব্যবহার করে ডিপিপ্লায়ার বনাম পাস-রেফারেন্স সিমানটিক ব্যবহার করে। dplyr এর ব্যবহার প্রয়োজনifelse() পুরো ভেক্টর , অন্যদিকে ডিটি সাবসেটটি আপডেট করবে এবং রেফারেন্সের মাধ্যমে আপডেট করবে (পুরো টিটি ফিরে আসবে)। সুতরাং, এই অনুশীলনের জন্য, ডিটি যথেষ্ট দ্রুততর হবে।

আপনি বিকল্পভাবে প্রথমে সাবসেট করতে পারবেন, তারপরে আপডেট করুন এবং শেষ পর্যন্ত পুনরায় সংশোধন করতে পারেন:

dt.sub <- dt[dt$measure == "exit",] %>%
  mutate(qty.exit= qty, cf= 0, delta.watts= 13)

dt.new <- rbind(dt.sub, dt[dt$measure != "exit",])

তবে ডিটি যথেষ্ট দ্রুততর হবে: (আইপি 10 এর নতুন উত্তর ব্যবহার করতে সম্পাদিত)

library(data.table)
library(dplyr)
library(microbenchmark)
microbenchmark(dt= {dt <- dt[measure == 'exit', 
                            `:=`(qty.exit = qty,
                                 cf = 0,
                                 delta.watts = 13)]},
               eipi10= {dt[dt$measure=="exit",] %<>% mutate(qty.exit = qty,
                                cf = 0,  
                                delta.watts = 13)},
               alex= {dt.sub <- dt[dt$measure == "exit",] %>%
                 mutate(qty.exit= qty, cf= 0, delta.watts= 13)

               dt.new <- rbind(dt.sub, dt[dt$measure != "exit",])})


Unit: microseconds
expr      min        lq      mean   median       uq      max neval cld
     dt  591.480  672.2565  747.0771  743.341  780.973 1837.539   100  a 
 eipi10 3481.212 3677.1685 4008.0314 3796.909 3936.796 6857.509   100   b
   alex 3412.029 3637.6350 3867.0649 3726.204 3936.985 5424.427   100   b

10

আমি কেবল এটি পেরেছি এবং সত্যিই পছন্দ করি mutate_cond() @G দ্বারা G গ্রোথেন্ডিক, তবে ভেবেছিল এটি নতুন ভেরিয়েবলগুলি পরিচালনা করতেও কার্যকর হতে পারে। সুতরাং, নীচে দুটি সংযোজন রয়েছে:

সম্পর্কিত নয়: দ্বিতীয় শেষ লাইনটি dplyrব্যবহার করে কিছুটা আরও তৈরি করেছেfilter()

শুরুতে তিনটি নতুন লাইন ব্যবহারের জন্য ভেরিয়েবলের নাম পেয়ে থাকে mutate()এবং ডেটা ফ্রেমে কোনও নতুন পরিবর্তনশীল হওয়ার আগেই আরম্ভ করে mutate()data.frameব্যবহারের অবশিষ্টাংশের জন্য নতুন ভেরিয়েবলগুলি আরম্ভ করা হয় new_init, যা NAডিফল্ট হিসাবে ( ) মিস করা থাকে ।

mutate_cond <- function(.data, condition, ..., new_init = NA, envir = parent.frame()) {
  # Initialize any new variables as new_init
  new_vars <- substitute(list(...))[-1]
  new_vars %<>% sapply(deparse) %>% names %>% setdiff(names(.data))
  .data[, new_vars] <- new_init

  condition <- eval(substitute(condition), .data, envir)
  .data[condition, ] <- .data %>% filter(condition) %>% mutate(...)
  .data
}

আইরিস ডেটা ব্যবহার করে এখানে কয়েকটি উদাহরণ দেওয়া হয়েছে:

Petal.Lengthযেখানে 88 তে পরিবর্তন করুন Species == "setosa"। এটি মূল ফাংশনের পাশাপাশি এই নতুন সংস্করণেও কাজ করবে।

iris %>% mutate_cond(Species == "setosa", Petal.Length = 88)

উপরের মতো একই, তবে একটি নতুন ভেরিয়েবল তৈরি করুন x( NAসারিগুলিতে শর্তটি অন্তর্ভুক্ত নয়)। এর আগে সম্ভব হয়নি।

iris %>% mutate_cond(Species == "setosa", Petal.Length = 88, x = TRUE)

উপরের মতো একই, তবে শর্তের অন্তর্ভুক্ত নেই সারিগুলি xFALSE এ সেট করা আছে।

iris %>% mutate_cond(Species == "setosa", Petal.Length = 88, x = TRUE, new_init = FALSE)

এই উদাহরণটি দেখায় যে কীভাবে বিভিন্ন মান সহ একাধিক নতুন ভেরিয়েবল সূচনা new_initকরতে সেট করা যায় list। এখানে দুটি নতুন ভেরিয়েবল তৈরি করা হয়েছে বাদ দেওয়া সারিগুলি বিভিন্ন মান ব্যবহার করে ( xআরম্ভ হিসাবে FALSE, yহিসাবে NA) আরম্ভ করা হচ্ছে

iris %>% mutate_cond(Species == "setosa" & Sepal.Length < 5,
                  x = TRUE, y = Sepal.Length ^ 2,
                  new_init = list(FALSE, NA))

আপনার mutate_condফাংশনটি আমার ডেটাসেটে একটি ত্রুটি টানছে এবং গ্রোথেন্ডিকস'স ফাংশনটি তা করে না। Error: incorrect length (4700), expecting: 168ফিল্টার ফাংশনের সাথে সম্পর্কিত বলে মনে হচ্ছে।
আরএইচএ

আপনি কি এটি একটি লাইব্রেরিতে রেখেছেন বা এটি কোনও কার্য হিসাবে আনুষ্ঠানিকভাবে রেখেছেন? এটি কোনও মস্তিষ্কের মতো বলে মনে হচ্ছে, বিশেষত সমস্ত উন্নতি সহ।
নেটলেট

4
না। আমি মনে করি এই সময়ে dplyr এর সাথে সর্বোত্তম পন্থা হ'ল মিউটেটের সাথে if_elseবা একত্রিত করা case_when
সাইমন জ্যাকসন

আপনি কি এই পদ্ধতির একটি উদাহরণ (বা লিঙ্ক) সরবরাহ করতে পারেন?
নেটলেট

6

mutate_cond একটি দুর্দান্ত ফাংশন, তবে শর্তটি তৈরি করতে ব্যবহৃত কলাম (গুলি) এ যদি কোনও NA থাকে তবে এটি একটি ত্রুটি দেয়। আমি অনুভব করি যে শর্তসাপেক্ষে পরিবর্তিত হওয়া উচিত এই জাতীয় সারিগুলি একা ছেড়ে। এটি ফিল্টার () এর আচরণের সাথে মিলে যায়, যা শর্তটি সত্য হলে সারিগুলি দেয়, তবে FALSE এবং NA সহ উভয় সারি বাদ দেয়।

এই ছোট পরিবর্তন সঙ্গে ফাংশন একটি কবজ মত কাজ করে:

mutate_cond <- function(.data, condition, ..., envir = parent.frame()) {
    condition <- eval(substitute(condition), .data, envir)
    condition[is.na(condition)] = FALSE
    .data[condition, ] <- .data[condition, ] %>% mutate(...)
    .data
}

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

যদি এটি আপনার পক্ষে দরকারী হয় তবে এই ফাংশনটি একটি ছোট প্যাকে পাওয়া যায় যা আমি লিখেছিলাম, "জুলটিলস"। এটি সিআরএন-তে নেই তবে আপনি এটি রিমোটগুলি ব্যবহার করে ইনস্টল করতে পারেন :: ইনস্টল_গিথুব ("টরফসন / জুলটিলস")
ম্যাগনাস

4

আমি আসলে এর কোনও পরিবর্তন দেখতে পাচ্ছি না dplyrএটি এটিকে আরও সহজ করে তুলবে। case_whenএক কলামের জন্য যখন একাধিক বিভিন্ন শর্ত এবং ফলাফল রয়েছে তখন এটি দুর্দান্ত তবে এটি যেখানে আপনি এক শর্তের ভিত্তিতে একাধিক কলাম পরিবর্তন করতে চান সেখানে এই ক্ষেত্রে সহায়ক হয় না। একইভাবে, recodeআপনি যদি একটি কলামে একাধিক বিভিন্ন মান প্রতিস্থাপন করছেন তবে একই সাথে একাধিক কলামে এটি করতে সহায়তা না করে টাইপিং সংরক্ষণ করে। পরিশেষে, mutate_atইত্যাদি কেবল কলামের নামগুলিতে ডেটাফ্রেমের সারিগুলিতে নয় শর্তাবলী প্রয়োগ করে। আপনি সম্ভাব্যভাবে মিউটেট_এটের জন্য একটি ফাংশন লিখতে পারেন যা এটি করবে তবে আপনি কীভাবে এটি আলাদা কলামের জন্য আলাদাভাবে আচরণ করবেন তা আমি বুঝতে পারি না।

যে এখানে বলেছিল আমি এটি ব্যবহার কিভাবে কাছে হবে nestফর্ম tidyrএবং mapথেকে purrr

library(data.table)
library(dplyr)
library(tidyr)
library(purrr)

# Create some sample data
set.seed(1)
dt <- data.table(site = sample(1:6, 50, replace=T),
                 space = sample(1:4, 50, replace=T),
                 measure = sample(c('cfl', 'led', 'linear', 'exit'), 50, 
                                  replace=T),
                 qty = round(runif(50) * 30),
                 qty.exit = 0,
                 delta.watts = sample(10.5:100.5, 50, replace=T),
                 cf = runif(50))

dt2 <- dt %>% 
  nest(-measure) %>% 
  mutate(data = if_else(
    measure == "exit", 
    map(data, function(x) mutate(x, qty.exit = qty, cf = 0, delta.watts = 13)),
    data
  )) %>%
  unnest()

4
কেবলমাত্র আমি যা পরামর্শ দিই তা হ'লnest(-measure)group_by
ডেভ গ্রুইনওয়াল্ড

@ ডেভগ্রুইনওয়াল্ড পরামর্শ প্রতিফলিত করতে সম্পাদিত
24

4

একটি সংক্ষিপ্ত সমাধান হ'ল ফিল্টারড সাবসেটটিতে রূপান্তর করা এবং তারপরে সারণির অ-প্রস্থান সারিগুলি যুক্ত করা:

library(dplyr)

dt %>% 
    filter(measure == 'exit') %>%
    mutate(qty.exit = qty, cf = 0, delta.watts = 13) %>%
    rbind(dt %>% filter(measure != 'exit'))

3

তৈরির সাথে সাথে rlangগ্রোথেন্ডিকের 1a উদাহরণের একটি সামান্য পরিবর্তিত সংস্করণ সম্ভব হয়, envirযুক্তির প্রয়োজনীয়তা অপসারণ করার সাথে সাথে স্বয়ংক্রিয়ভাবে তৈরি enquo()হওয়া পরিবেশটিকে ক্যাপচার করে .p

mutate_rows <- function(.data, .p, ...) {
  .p <- rlang::enquo(.p)
  .p_lgl <- rlang::eval_tidy(.p, .data)
  .data[.p_lgl, ] <- .data[.p_lgl, ] %>% mutate(...)
  .data
}

dt %>% mutate_rows(measure == "exit", qty.exit = qty, cf = 0, delta.watts = 13)

2

আপনি ডেটাসেট বিভক্ত করতে পারেন এবং TRUEঅংশে একটি নিয়মিত মিউটেট কল করতে পারেন ।

dplyr 0.8 এর ফাংশনটি বৈশিষ্ট্যযুক্ত group_splitযা গোষ্ঠী দ্বারা বিভক্ত হয় (এবং গ্রুপগুলি কলগুলিতে সরাসরি সংজ্ঞায়িত করা যায়) সুতরাং আমরা এটি এখানে ব্যবহার করব, তবে base::splitপাশাপাশি কাজ করে।

library(tidyverse)
df1 %>%
  group_split(measure == "exit", keep=FALSE) %>% # or `split(.$measure == "exit")`
  modify_at(2,~mutate(.,qty.exit = qty, cf = 0, delta.watts = 13)) %>%
  bind_rows()

#    site space measure qty qty.exit delta.watts          cf
# 1     1     4     led   1        0        73.5 0.246240409
# 2     2     3     cfl  25        0        56.5 0.360315879
# 3     5     4     cfl   3        0        38.5 0.279966850
# 4     5     3  linear  19        0        40.5 0.281439486
# 5     2     3  linear  18        0        82.5 0.007898384
# 6     5     1  linear  29        0        33.5 0.392412729
# 7     5     3  linear   6        0        46.5 0.970848817
# 8     4     1     led  10        0        89.5 0.404447182
# 9     4     1     led  18        0        96.5 0.115594622
# 10    6     3  linear  18        0        15.5 0.017919745
# 11    4     3     led  22        0        54.5 0.901829577
# 12    3     3     led  17        0        79.5 0.063949974
# 13    1     3     led  16        0        86.5 0.551321441
# 14    6     4     cfl   5        0        65.5 0.256845013
# 15    4     2     led  12        0        29.5 0.340603733
# 16    5     3  linear  27        0        63.5 0.895166931
# 17    1     4     led   0        0        47.5 0.173088800
# 18    5     3  linear  20        0        89.5 0.438504370
# 19    2     4     cfl  18        0        45.5 0.031725246
# 20    2     3     led  24        0        94.5 0.456653397
# 21    3     3     cfl  24        0        73.5 0.161274319
# 22    5     3     led   9        0        62.5 0.252212124
# 23    5     1     led  15        0        40.5 0.115608182
# 24    3     3     cfl   3        0        89.5 0.066147321
# 25    6     4     cfl   2        0        35.5 0.007888337
# 26    5     1  linear   7        0        51.5 0.835458916
# 27    2     3  linear  28        0        36.5 0.691483644
# 28    5     4     led   6        0        43.5 0.604847889
# 29    6     1  linear  12        0        59.5 0.918838163
# 30    3     3  linear   7        0        73.5 0.471644760
# 31    4     2     led   5        0        34.5 0.972078100
# 32    1     3     cfl  17        0        80.5 0.457241602
# 33    5     4  linear   3        0        16.5 0.492500255
# 34    3     2     cfl  12        0        44.5 0.804236607
# 35    2     2     cfl  21        0        50.5 0.845094268
# 36    3     2  linear  10        0        23.5 0.637194873
# 37    4     3     led   6        0        69.5 0.161431896
# 38    3     2    exit  19       19        13.0 0.000000000
# 39    6     3    exit   7        7        13.0 0.000000000
# 40    6     2    exit  20       20        13.0 0.000000000
# 41    3     2    exit   1        1        13.0 0.000000000
# 42    2     4    exit  19       19        13.0 0.000000000
# 43    3     1    exit  24       24        13.0 0.000000000
# 44    3     3    exit  16       16        13.0 0.000000000
# 45    5     3    exit   9        9        13.0 0.000000000
# 46    2     3    exit   6        6        13.0 0.000000000
# 47    4     1    exit   1        1        13.0 0.000000000
# 48    1     1    exit  14       14        13.0 0.000000000
# 49    6     3    exit   7        7        13.0 0.000000000
# 50    2     4    exit   3        3        13.0 0.000000000

যদি সারি অর্ডারটি গুরুত্বপূর্ণ হয় tibble::rowid_to_columnতবে প্রথমে ব্যবহার dplyr::arrangeকরুন rowidএবং তারপরে শেষ পর্যন্ত এটি নির্বাচন করুন।

তথ্য

df1 <- data.frame(site = sample(1:6, 50, replace=T),
                 space = sample(1:4, 50, replace=T),
                 measure = sample(c('cfl', 'led', 'linear', 'exit'), 50, 
                                  replace=T),
                 qty = round(runif(50) * 30),
                 qty.exit = 0,
                 delta.watts = sample(10.5:100.5, 50, replace=T),
                 cf = runif(50),
                 stringsAsFactors = F)

2

আমার মনে হয় এর আগে এই উত্তরটির কথা বলা হয়নি। এটি 'ডিফল্ট' data.tableসমাধানের মতো প্রায় দ্রুত গতিতে চলে ...

ব্যবহার base::replace()

df %>% mutate( qty.exit = replace( qty.exit, measure == 'exit', qty[ measure == 'exit'] ),
                          cf = replace( cf, measure == 'exit', 0 ),
                          delta.watts = replace( delta.watts, measure == 'exit', 13 ) )

প্রতিস্থাপনের মানটি পুনর্ব্যবহার করে, সুতরাং আপনি যখন qtyকলমের মানগুলি কলমে প্রবেশ করতে চান তখন আপনাকেও qty.exitসাবসেট করতে হবে qty ... সুতরাং qty[ measure == 'exit']প্রথম প্রতিস্থাপনের ক্ষেত্রে ..

এখন, আপনি সম্ভবত measure == 'exit'সব সময় পুনরায় টাইপ করতে চাইবেন না ... যাতে আপনি সেই নির্বাচনটি যুক্ত একটি সূচক-ভেক্টর তৈরি করতে পারেন এবং উপরের ফাংশনগুলিতে এটি ব্যবহার করতে পারেন।

#build an index-vector matching the condition
index.v <- which( df$measure == 'exit' )

df %>% mutate( qty.exit = replace( qty.exit, index.v, qty[ index.v] ),
               cf = replace( cf, index.v, 0 ),
               delta.watts = replace( delta.watts, index.v, 13 ) )

মানদণ্ড

# Unit: milliseconds
#         expr      min       lq     mean   median       uq      max neval
# data.table   1.005018 1.053370 1.137456 1.112871 1.186228 1.690996   100
# wimpel       1.061052 1.079128 1.218183 1.105037 1.137272 7.390613   100
# wimpel.index 1.043881 1.064818 1.131675 1.085304 1.108502 4.192995   100

1

সাধারণ ডিপ্লায়ার সিনট্যাক্সের সাথে ব্রেক করার ব্যয়ে আপনি withinবেস থেকে ব্যবহার করতে পারেন :

dt %>% within(qty.exit[measure == 'exit'] <- qty[measure == 'exit'],
              delta.watts[measure == 'exit'] <- 13)

পাইপের সাথে এটি ভালভাবে সংহত হয়েছে বলে মনে হচ্ছে এবং আপনি এটির ভিতরে যা চান তা করতে পারেন।


এটি লিখিত হিসাবে কাজ করে না কারণ দ্বিতীয় কার্যভারটি আসলে ঘটে না। তবে আপনি যদি করেন dt %>% within({ delta.watts[measure == 'exit'] <- 13 ; qty.exit[measure == 'exit'] <- qty[measure == 'exit'] ; cf[measure == 'exit'] <- 0 })তবে এটি কাজ করে
24
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.