R中的条件数据框突变与magrittr和dplyr
Posted
技术标签:
【中文标题】R中的条件数据框突变与magrittr和dplyr【英文标题】:Conditional dataframe mutations in R with magrittr and dplyr 【发布时间】:2016-03-13 15:52:10 【问题描述】:我想使用 magrittr 和 dplyr 的简洁性来根据其他列中的值在列子集中的行之间复制单个值。这是一个简单的例子;我想将这个想法应用到具有多个条件的大型数据集的许多列中。
取数据框df <- data.frame(a = 1:5, b = 6:10, x = 11:15, y = 16:20)
:
a b x y
1 6 11 16
2 7 12 17
3 8 13 18
4 9 14 19
5 10 15 20
对于a = 5
所在的行,我想将x
和y
的值替换为b = 7
所在行的值,给出:
a b x y
1 6 11 16
2 7 12 17
3 8 13 18
4 9 14 19
5 10 12 17
此尝试失败:
foo <- function(x)ifelse(df$a == 5, df[df$b == 7, .(df$x)], x)
df %<>% mutate_each(funs(foo), x, y)
我能得到的最接近的是:
bar <- function(x)ifelse(df$a == 5, df[df$b == 7, "x"], x)
df %<>% mutate_each(funs(bar), x, y)
但这是不正确的,因为它将两个值都替换为来自x
的值,而不是分别替换为x
和y
。
感谢您的建议。
【问题讨论】:
%<>%
和 %>%
之间的区别是什么?
x %<>% f
来自magrittr
包,相当于普通模式x <- x %>% f
。
%>%
也来自magrittr
包...
@DavidArenburg %>%
将仅在加载 dplyr
的情况下工作,而目前使用 CRAN 版本,使用 %<>%
需要加载 magrittr
。没错,%>%
来自 magrittr
到 dplyr
,但对于最终用户来说,知道要加载哪些包更相关!
@antoine-sac 好吧,这就是你的意见,伙计。
【参考方案1】:
您可以使用mutate_each
和replace
来做到这一点:
df %>% mutate_each(funs(replace(., a==5, nth(., which(b==7)))), x, y)
输出:
a b x y
1 1 6 11 16
2 2 7 12 17
3 3 8 13 18
4 4 9 14 19
5 5 10 12 17
或者根据@docendodiscimus 的评论,它可以进一步缩短为(并且可能[
也比which
更好):
df %>% mutate_each(funs(replace(., a==5, .[b==7])), x, y)
【讨论】:
谢谢,但我想将此方法应用于可能在其他地方定义的大量列,因此这将很快变得笨拙。 @PatrickHogan 我没有在你的问题中注意到这一点。我也许可以调整上面的代码。 更新了答案。现在我认为这应该符合您的需求。 不错的一个!可以缩短为df %>% mutate_each(funs(replace(., a==5, .[b==7])), x, y)
啊,很好的改进@docendodiscimus 谢谢。我也加一下。【参考方案2】:
仅提及data.table
解决方案是:
require(data.table)
setDT(df)[a == 5, c("x", "y") := df[b == 7, .SD, .SDcols = c("x", "y")]]
> df
a b x y
1: 1 6 11 16
2: 2 7 12 17
3: 3 8 13 18
4: 4 9 14 19
5: 5 10 12 17
或者,您也可以使用:
cols <- c("x", "y")
setDT(df)[a == 5, (cols) := df[b == 7, .SD, .SDcols = cols]]
# or
cols <- c("x", "y")
setDT(df)[a == 5, (cols) := df[b == 7, cols, with = FALSE]]
【讨论】:
DT <- setDT(df)
几乎没有意义。因为df
现在也是一个 data.table 并且已通过引用更新。
@Arun:我完全同意。当我开始使用data.table
时,通过引用更新 的概念对我来说非常陌生。当问题要求dplyr
解决方案时,我认为我的答案更容易理解。
我明白了.. 那么最好使用 as.data.table 。还使用with=FALSE
或.SD + .SDcols
将有助于表明它很容易扩展到许多列。
@Arun:看看我的编辑。我不明白您使用with=FALSE
是什么意思。随意编辑。
我冒昧地改进了您的答案。希望你不要介意。【参考方案3】:
如果您的主要要求是在更长的 dplyr 管道中应用该函数,您可以执行以下示例:
foo <- function(df, cols = c("x", "y"))
df[df$a == 5, cols] <- df[df$b == 7, cols]
df
df %>% ... %>% foo(c("x", "y")) %>% ...
# a b x y
#1 1 6 11 16
#2 2 7 12 17
#3 3 8 13 18
#4 4 9 14 19
#5 5 10 12 17
【讨论】:
以上是关于R中的条件数据框突变与magrittr和dplyr的主要内容,如果未能解决你的问题,请参考以下文章