2017-07-16 55 views
3

我不知道是否有一个dplyr相当于dplyr相当于DF [DF == X] < - Ÿ

df <- data.frame(A=1:5,B=2:6,C=-1:3) 
df[df==2] <- 10 

我在寻找

df %>% <??> 

也就是说,声明即与其他dplyr动词链接

+1

不是我所知道的,但你找到它了吗?这似乎是在https://stackoverflow.com/questions/34096162/dplyr-mutate-replace-on-a-subset-of-rows或https://stackoverflow.com/questions/23078891/how-to-更新价值与dplyr –

+0

@DavidArenburg我总是试图看看。并不意味着我总是成功。感谢您的链接...可能的答案是软* NO *,考虑到第一个链接写了一个函数来做到这一点。第二个链接只改变了一列,但看起来像一个很有前途的开始...... – CPak

+0

虽然我不是最新的'dplyr'。它似乎每天都在发展。更不用说它是'tidyverse'的一部分,所以你可能需要通过约1K的功能来确定。另外,也许'magrittr'有东西可以提供。关于第二个环节,这只是标准的基础'ifelse',同样喜欢在他们使用'\'[<第一个环节 - data.frame \''和'replace' - 所有基础R东西卧底(没有理由IMO )。 –

回答

7

1)替换试试这个。它只需要magrittr虽然dplyr进口magrittr相关的部分,因此将与dplyr工作太:

df %>% replace(. == 2, 10) 

,并提供:

A B C 
1 1 10 -1 
2 10 3 0 
3 3 4 1 
4 4 5 10 
5 5 6 3 

1A)覆盖注意的是,以上的非破坏性如此如果您想更新df,那么你将需要将其分配回:

df <- df %>% replace(. == 2, 10) 

df %>% replace(. == 2, 10) -> df 

或使用magrittr %<>%运营商消除引用df两次:

df %<>% replace(. == 2, 10) 

2)算术这也将工作:

df %>% { 10 * (. == 2) + . * (. != 2) } 
+0

即使整洁...感谢 – CPak

+0

所以它只是一个像其他环节基础R解决方案。我没有看到任何dplyr在这里相关(这是关于的问题)。无论我怎么看它是任何比'替换(DF,DF == 2,10)更好'或'DF [DF = = 2] < - 10' –

+2

我指出很清楚,它只是需要magrittr还要注意的是, %<>%解决方案只需要一个基准的df与2的引用。我认为这个问题的意图是如何做到这一点。 –

2

的OP的问题是关于如何使用dplyr代替值,并且由G.Gotothendieck解决。但我很好奇,基于dplyrdata.table和base R的不同方法之间的性能差异如何。于是我设计并执行了以下基准测试。

# Load package 
library(dplyr) 
library(data.table) 
library(microbenchmark) 

# Create example data frame 
df <- data.frame(A = 1:5, B = 2:6, C = -1:3) 
# Convert to data.table 
dt <- as.data.table(df) 

# Method 1: Use mutate_all and ifelse 
F1 = function(df){df %>% mutate_all(funs(ifelse(. == 2, 10, .)))} 
# Method 2: Use mutate_all and replace 
F2 = function(df){df %>% mutate_all(funs(replace(., . == 2, 10)))} 
# Method 3: Use replace 
F3 = function(df){df %>% replace(. == 2, 10)} 
# Method 4: Base R data frame assignment 
F4 = function(df){ 
    df[df == 2] <- 10 
    return(df) 
} 

# Benchmarking 
microbenchmark(
    M1 = F1(df), 
    M2 = F2(df), 
    M3 = F3(df), 
    M4 = F4(df), 
    # Same as M4, but use data.table object as input 
    M5 = F4(dt) 
) 

Unit: microseconds 
expr  min   lq  mean  median   uq  max neval 
    M1 8634.974 13028.7975 17224.4669 14907.3735 19496.5275 79750.182 100 
    M2 8925.565 12626.2675 16698.7412 15551.7410 18658.1125 35468.760 100 
    M3 282.252 391.6240 591.2534 553.5980 647.8965 3290.797 100 
    M4 163.578 252.1025 423.7627 349.6080 420.8125 5415.382 100 
    M5 228.367 333.2495 596.1735 440.3775 555.5230 7506.609 100 

结果表明,与mutata_allifelseM1)或replaceM2)比其他方法慢得多。使用replace与管道(M3)速度较快,但仍比基准R(M4)慢一点。将data.frame转换为data.table,然后应用分配替换(M5)不会比M4更快。

所以,我认为在这种情况下,没有特别的需要使用dplyr函数,因为它不比基准R方法(M4)更快。也不需要将data.frame转换为data.table如果需要管道操作。我们可以使用管道replaceM3)。或者,我们可以定义一个函数,如F4,并将其放入管道操作中。

+0

感谢您的配合。很高兴知道他们如何在表现中积累。根据我的经验,非答案答案*有争议*,但我认为它值得一看。 – CPak

+1

成语一致性通常胜过我在现实世界中 – hrbrmstr

+0

@hrbrmstr我同意丰富的经验,“微秒性能”的好处。成语一致性有助于代码可读性。对于小数据帧,习语一致性比“微秒性能”更重要。但是,如果有很多数据帧或大数据帧,“微秒性能”可能很重要。当我说“在这种情况下”时,我不仅仅是指这个小数据框,而是这种一般操作。 – www