dplyr biến đổi / thay thế một số cột trên một tập hợp con các hàng


85

Tôi đang trong quá trình thử quy trình làm việc dựa trên dplyr (thay vì sử dụng chủ yếu là data.table như tôi đã quen) và tôi đã gặp phải một vấn đề mà tôi không thể tìm thấy giải pháp dplyr tương đương . Tôi thường gặp phải trường hợp tôi cần cập nhật / thay thế một số cột có điều kiện dựa trên một điều kiện duy nhất. Đây là một số mã ví dụ, với giải pháp data.table của tôi:

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

Có một giải pháp dplyr đơn giản cho cùng một vấn đề này không? Tôi muốn tránh sử dụng ifelse vì tôi không muốn phải nhập điều kiện nhiều lần - đây là một ví dụ đơn giản hóa, nhưng đôi khi có nhiều phép gán dựa trên một điều kiện duy nhất.

Xin được cảm ơn trước về sự giúp đỡ!

Câu trả lời:


81

Các giải pháp này (1) duy trì đường ống, (2) không ghi đè đầu vào và (3) chỉ yêu cầu điều kiện được chỉ định một lần:

1a) mutate_cond Tạo một hàm đơn giản cho khung dữ liệu hoặc bảng dữ liệu có thể được kết hợp vào đường ống. Hàm này giống như mutatenhưng chỉ hoạt động trên các hàng thỏa mãn điều kiện:

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)

1b) mutate_last Đây là một hàm thay thế cho các khung dữ liệu hoặc bảng dữ liệu giống như vậy mutatenhưng chỉ được sử dụng trong group_by(như trong ví dụ bên dưới) và chỉ hoạt động trên nhóm cuối cùng thay vì mọi nhóm. Lưu ý rằng TRUE> FALSE nên nếu group_bychỉ định một điều kiện thì mutate_lastsẽ chỉ hoạt động trên các hàng thỏa mãn điều kiện đó.

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) điều kiện ra yếu tố loại bỏ điều kiện bằng cách biến nó thành một cột bổ sung mà sau này sẽ bị loại bỏ. Sau đó, sử dụng ifelse, replacehoặc số học với logic như minh họa. Điều này cũng hoạt động cho các bảng dữ liệu.

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 Chúng tôi có thể sử dụng SQL updatethông qua gói sqldf trong đường dẫn cho khung dữ liệu (nhưng không phải bảng dữ liệu trừ khi chúng tôi chuyển đổi chúng - điều này có thể đại diện cho một lỗi trong dplyr. Xem dplyr issue 1579 ). Có vẻ như chúng tôi đang sửa đổi đầu vào trong mã này một cách không thể tránh khỏi do sự tồn tại của updatenhưng trên thực tế, updatenó đang hoạt động trên bản sao của đầu vào trong cơ sở dữ liệu được tạo tạm thời chứ không phải trên đầu vào thực tế.

library(sqldf)

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

4) row_case_when Cũng kiểm tra row_case_whenđược xác định trong Trả lại một tibble: làm thế nào để vectơ hóa với case_when? . Nó sử dụng một cú pháp tương tự như case_whennhưng áp dụng cho các hàng.

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

Lưu ý 1: Chúng tôi sử dụng điều này như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))

Lưu ý 2: Vấn đề làm thế nào để dễ dàng chỉ định cập nhật một tập hợp con của các hàng cũng được thảo luận trong các vấn đề dplyr 134 , 631 , 15181573 với 631 là chủ đề chính và 1573 là đánh giá các câu trả lời ở đây.


1
Câu trả lời xuất sắc, cảm ơn! Mutate_cond của bạn và mutate_when của @Kevin Ushey đều là giải pháp tốt cho vấn đề này. Tôi nghĩ rằng tôi có một chút ưu tiên cho khả năng đọc / tính linh hoạt của mutate_when, nhưng tôi sẽ cho câu trả lời này là "kiểm tra" cho sự kỹ lưỡng.
Chris Newton

Tôi thực sự thích cách tiếp cận mutate_cond. Có vẻ như tôi cũng thích chức năng này hoặc một cái gì đó rất gần với nó đáng được đưa vào dplyr và sẽ là giải pháp tốt hơn so với VectorizedSwitch (được thảo luận trong github.com/hadley/dplyr/issues/1573 ) cho trường hợp sử dụng mà mọi người đang nghĩ về đây ...
Magnus

Tôi yêu mutate_cond. Các tùy chọn khác nhau nên là các câu trả lời riêng biệt.
Holger Brandl

Đã vài năm trôi qua và các vấn đề trên github dường như bị đóng và khóa. Có một giải pháp chính thức cho vấn đề này?
static_rtti 14/12/18

27

Bạn có thể làm điều này với magrittrđường ống hai chiều của %<>%:

library(dplyr)
library(magrittr)

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

Điều này làm giảm số lượng gõ, nhưng vẫn chậm hơn nhiều data.table.


Trên thực tế, bây giờ tôi đã có cơ hội kiểm tra điều này, tôi muốn có một giải pháp tránh phải đặt tập hợp con bằng cách sử dụng ký hiệu dt [dt $ Measure == 'exit',], vì điều đó có thể khó sử dụng hơn dt tên.
Chris Newton

Chỉ là FYI, nhưng giải pháp này sẽ chỉ hoạt động nếu data.frame/ tibbleđã chứa cột được xác định bởi mutate. Nó sẽ không hoạt động nếu bạn đang cố gắng thêm một cột mới, ví dụ: lần đầu tiên chạy qua một vòng lặp và sửa đổi a data.frame.
Ursus Frost

@UrsusFrost thêm một cột mới chỉ là một tập hợp con của tập dữ liệu có vẻ lạ đối với tôi. Bạn thêm NA vào các hàng không được tập hợp con?
Baraliuh

@Baraliuh Vâng, tôi có thể đánh giá cao điều đó. Đó là một phần của vòng lặp trong đó tôi tăng và nối dữ liệu qua danh sách ngày tháng. Một vài ngày đầu tiên phải được xử lý khác với những ngày tiếp theo vì nó đang tái tạo các quy trình kinh doanh trong thế giới thực. Trong các lần lặp lại tiếp theo, tùy thuộc vào điều kiện của ngày, dữ liệu được tính toán khác nhau. Do điều kiện, tôi không muốn vô tình thay đổi ngày tháng trước trong data.frame. FWIW, tôi chỉ quay lại sử dụng data.tablethay dplyrvì vì ibiểu thức của nó xử lý điều này dễ dàng - cộng với vòng lặp tổng thể chạy nhanh hơn nhiều.
Ursus Frost

18

Đây là một giải pháp tôi thích:

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
}

Nó cho phép bạn viết những thứ như vd

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

khá dễ đọc - mặc dù nó có thể không hiệu quả như nó có thể.


14

Như eipi10 cho thấy ở trên, không có cách nào đơn giản để thực hiện thay thế tập hợp con trong dplyr vì DT sử dụng ngữ nghĩa chuyển qua tham chiếu so với dplyr sử dụng giá trị chuyển. dplyr yêu cầu sử dụng ifelse()trên toàn bộ vectơ, trong khi DT sẽ thực hiện tập hợp con và cập nhật bằng tham chiếu (trả về toàn bộ DT). Vì vậy, đối với bài tập này, DT sẽ nhanh hơn đáng kể.

Ngoài ra, bạn có thể tập hợp con trước, sau đó cập nhật và cuối cùng kết hợp lại:

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

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

Nhưng DT sẽ nhanh hơn đáng kể: (được chỉnh sửa để sử dụng câu trả lời mới của eipi10)

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

Tôi chỉ tình cờ xem được điều này và thực sự thích mutate_cond()@G. Grothendieck, nhưng nghĩ rằng nó có thể hữu ích khi cũng xử lý các biến mới. Vì vậy, bên dưới có hai bổ sung:

Không liên quan: Dòng cuối cùng thứ hai được tạo thêm một chút dplyrbằng cách sử dụngfilter()

Ba dòng mới ở đầu lấy tên biến để sử dụng mutate()và khởi tạo bất kỳ biến mới nào trong khung dữ liệu trước khi mutate()xảy ra. Các biến mới được khởi tạo cho phần còn lại của việc data.framesử dụng new_init, được đặt thành thiếu ( NA) làm mặc định.

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
}

Dưới đây là một số ví dụ sử dụng dữ liệu mống mắt:

Thay đổi Petal.Lengththành 88 ở đâu Species == "setosa". Điều này sẽ hoạt động trong chức năng gốc cũng như phiên bản mới này.

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

Tương tự như trên, nhưng cũng tạo một biến mới x( NAtrong các hàng không có trong điều kiện). Không thể trước đây.

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

Tương tự như trên, nhưng các hàng không có trong điều kiện cho xđược đặt thành FALSE.

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

Ví dụ này cho thấy cách new_initcó thể được đặt thành a listđể khởi tạo nhiều biến mới với các giá trị khác nhau. Ở đây, hai biến mới được tạo với các hàng bị loại trừ được khởi tạo bằng các giá trị khác nhau (được xkhởi tạo là FALSE, ynhư NA)

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

mutate_condHàm của bạn gặp lỗi trên tập dữ liệu của tôi và hàm của Grothendiecks thì không. Error: incorrect length (4700), expecting: 168Có vẻ liên quan đến chức năng bộ lọc.
RHA

Bạn đã đưa nó vào thư viện hay chính thức hóa nó như một hàm chưa? Nó có vẻ như không có trí tuệ, đặc biệt là với tất cả các cải tiến.
Nettle

1
Không. Tôi nghĩ cách tốt nhất với dplyr tại thời điểm này là kết hợp mutate với if_elsehoặc case_when.
Simon Jackson

Bạn có thể cung cấp một ví dụ (hoặc liên kết) cho cách tiếp cận này không?
Cây tầm ma

6

mutate_cond là một hàm tuyệt vời, nhưng nó sẽ báo lỗi nếu có NA trong (các) cột được sử dụng để tạo điều kiện. Tôi cảm thấy rằng một đột biến có điều kiện chỉ nên để các hàng như vậy một mình. Điều này phù hợp với hành vi của filter (), trả về các hàng khi điều kiện là TRUE, nhưng bỏ qua cả hai hàng có FALSE và NA.

Với thay đổi nhỏ này, chức năng hoạt động giống như một sự quyến rũ:

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
}

Cảm ơn Magnus! Tôi đang sử dụng cái này để cập nhật một bảng chứa các hành động và thời gian cho tất cả các đối tượng tạo nên hoạt ảnh. Tôi gặp phải vấn đề NA vì dữ liệu rất đa dạng nên một số hành động không có ý nghĩa đối với một số đối tượng, vì vậy tôi có NA trong các ô đó. Mutate_cond khác ở trên bị lỗi, nhưng giải pháp của bạn hoạt động như một sự quyến rũ.
Phil van Kleur

Nếu điều này hữu ích cho bạn, chức năng này có sẵn trong một gói nhỏ mà tôi đã viết, "zulutils". Nó không có trên CRAN nhưng bạn có thể cài đặt nó bằng cách sử dụng điều khiển từ xa :: install_github ("torfason / zulutils")
Magnus

Tuyệt quá! Cảm ơn nhiều. Tôi vẫn đang sử dụng nó.
Phil van Kleur

4

Tôi thực sự không thấy bất kỳ thay đổi nào đối với dplyr điều đó sẽ làm cho việc này dễ dàng hơn nhiều. case_whenrất phù hợp khi có nhiều điều kiện và kết quả khác nhau cho một cột nhưng nó không hữu ích cho trường hợp này khi bạn muốn thay đổi nhiều cột dựa trên một điều kiện. Tương tự, hãy recodetiết kiệm việc nhập nếu bạn đang thay thế nhiều giá trị khác nhau trong một cột nhưng không giúp được việc làm như vậy trong nhiều cột cùng một lúc. Cuối cùng,mutate_at v.v. chỉ áp dụng các điều kiện cho tên cột chứ không phải các hàng trong khung dữ liệu. Bạn có thể viết một hàm cho mutate_at để làm điều đó nhưng tôi không thể tìm ra cách bạn sẽ làm cho nó hoạt động khác nhau cho các cột khác nhau.

Điều đó nói rằng đây là cách tôi sẽ tiếp cận nó bằng cách sử dụng nestbiểu mẫu tidyrmaptừ 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()

1
Chỉ có điều tôi muốn đề nghị là sử dụng nest(-measure)để tránh sựgroup_by
Dave Gruenewald

Đã chỉnh sửa để phản ánh đề xuất
@DaveGruenewald

4

Một giải pháp ngắn gọn sẽ là thực hiện đột biến trên tập hợp con đã lọc và sau đó thêm lại các hàng không thoát của bảng:

library(dplyr)

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

3

Với việc tạo ra rlang, có thể có phiên bản sửa đổi một chút của ví dụ 1a của Grothendieck, loại bỏ sự cần thiết của envirđối số, vì enquo()nắm bắt môi trường .pđược tạo tự động.

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

Bạn có thể tách tập dữ liệu và thực hiện lệnh gọi biến đổi thông thường trên TRUEphần này.

dplyr 0.8 có chức năng group_splitphân chia theo nhóm (và các nhóm có thể được xác định trực tiếp trong cuộc gọi) vì vậy chúng tôi sẽ sử dụng nó ở đây, nhưng cũng base::splithoạt động.

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

Nếu thứ tự hàng quan trọng, hãy sử dụng tibble::rowid_to_columntrước, sau đó dplyr::arrangebật rowidvà chọn nó cuối cùng.

dữ liệu

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

Tôi nghĩ rằng câu trả lời này đã không được đề cập trước đây. Nó chạy gần như nhanh bằng độ phân giải 'mặc định' data.table..

Sử dụng 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 ) )

thay thế tái chế giá trị thay thế, vì vậy khi bạn muốn giá trị của các cột được qtynhập vào cột qty.exit, bạn cũng phải tập hợp con qty ... do đó, qty[ measure == 'exit']trong lần thay thế đầu tiên ..

bây giờ, bạn có thể sẽ không muốn gõ lại measure == 'exit'mọi lúc ... vì vậy bạn có thể tạo một vector chỉ mục chứa lựa chọn đó và sử dụng nó trong các hàm ở trên.

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

điểm chuẩn

# 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

Với chi phí phá vỡ cú pháp dplyr thông thường, bạn có thể sử dụng withintừ cơ sở:

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

Nó dường như tích hợp tốt với đường ống và bạn có thể làm bất cứ điều gì bạn muốn bên trong nó.


Điều này không hoạt động như đã viết vì nhiệm vụ thứ hai không thực sự xảy ra. Nhưng nếu bạn làm dt %>% within({ delta.watts[measure == 'exit'] <- 13 ; qty.exit[measure == 'exit'] <- qty[measure == 'exit'] ; cf[measure == 'exit'] <- 0 })thì nó vẫn hoạt động
xem 24
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.