我一直在寻找但没有发现如何简化dplyr中的许多列。
我有此代码(有效):
library(dplyr)
library(magrittr)
data("PlantGrowth")
PlantGrowth %>% mutate (
a=if_else(group=="ctrl", weight*2, weight*100),
b=if_else(group=="ctrl", weight*1,5, weight/100),
c=if_else(group=="ctrl", weight*4, weight*100),
d=if_else(group=="ctrl", weight*5, weight/1000)
)
我不想重复这个条件。像这样:
PlantGrowth %>% mutate_if_foo (
group=="ctrl",{
a=weight*2,
b=weight*1,5,
c=weight*4,
d=weight*5
}
)%>% mutate_if_foo (
group!="ctrl",{
a=weight*100,
b=weight/100),
c=weight*100),
d=weight/1000)
}
)
我在mutate_if
,mutate_all
,mutate_at
和case_when
上找到了很多答案,但是他们没有回答我的问题。
请使用dplyr / tidyverse。
预先感谢
编辑
我尝试过@Rohit_das关于函数的想法。
mtcars %>% ( function(df) {
if (df$am==1){
df%>% mutate(
a=df$mpg*3,
b=df$cyl*10)
}else{
df%>% mutate(
a=df$disp*300,
d=df$cyl*1000)
}
})
但是我有警告消息:
In if (df$am == 1) { :
the condition has length > 1
and only the first element will be used
答案 0 :(得分:1)
不确定我是否在这里理解了这个问题。如果您只是想减少代码的冗长性,则只需创建一个自定义函数
customif = function(x,y) {
if_else(group=="ctrl", weight*x, weight*y)
}
然后您可以在mutate中以
形式调用此函数PlantGrowth %>% mutate (
a=customif(2,100),
b=customif(1,5, 1/100),
c=customif(4, 100),
d=customif(5, 1/1000)
)
答案 1 :(得分:0)
我想我用purrr找到了一个很好的解决方案。它使用输入的数据帧,然后使用每一列的新输入来动态命名新列a:d
。第一列将使用x = 2
,y = 100
和z = "a"
,然后是下一行,依此类推。像这样的函数式编程最酷的一点是,它很容易扩展。
library(tidyverse)
iterate <- tibble(x = c(2, 1.5, 4, 5),
y = c(100, 1/100, 100, 1/1000),
z = c("a", "b", "c", "d"))
fun <- function(x, y, z) {
PlantGrowth %>%
mutate(!!z := if_else(group == "ctrl", weight * x, weight * y)) %>%
select(3)
}
PlantGrowth %>%
bind_cols(
pmap_dfc(iterate, fun)
) %>%
as_tibble
哪一个给你相同的df:
# A tibble: 30 x 6
weight group a b c d
<dbl> <fct> <dbl> <dbl> <dbl> <dbl>
1 4.17 ctrl 8.34 6.26 16.7 20.8
2 5.58 ctrl 11.2 8.37 22.3 27.9
3 5.18 ctrl 10.4 7.77 20.7 25.9
4 6.11 ctrl 12.2 9.17 24.4 30.6
5 4.5 ctrl 9 6.75 18 22.5
答案 2 :(得分:0)
我想我已经找到了答案。我在mtcars
上进行了测试。我尚未在真实代码上进行测试。
如果我认为我的概念不对,请发表评论。
过滤器的条件必须是互斥的,否则我将重复一行。
library(dplyr)
library(magrittr)
library(tibble) # only if necessary to preserve rownames
mtcars %>% ( function(df) {
rbind(
(df
%>% tibble::rownames_to_column(.) %>%tibble::rowid_to_column(.) # to preserve rownames
%>%dplyr::filter(am==1)
%>%dplyr::mutate(
a=mpg*3,
b=cyl*10,d=NA)),
(df
%>% tibble::rownames_to_column(.) %>%tibble::rowid_to_column(.) # to preserve rownames
%>%dplyr::filter(am!=1)
%>%dplyr::mutate(
a=disp*3,
d=cyl*100,b=NA))
)
}) %>%arrange(rowid)