我有一张这样的表:
require(dplyr)
y = data.frame(a.foo=rnorm(10),b.foo=rnorm(10), a.bar=rnorm(10), b.bar=rnorm(10), a.baz=rnorm(10), b.baz=rnorm(10))
我经常最终做这样的事情(在这个例子中简化为+
)
y %>% mutate(z.foo=(a.foo+b.foo),z.bar=(a.bar+b.bar),z.baz=(a.baz+b.baz))
有时会有各种各样的这些,我想知道是否有使用像matches
这样的简写方式,因为唯一的模式是我通常想做的z.* = a.* + b.*
。有没有一种优雅的方式来表达dplyr
中没有硬编码的情况?
答案 0 :(得分:2)
你可以通过标准评估和lazyeval
来做到这一点,虽然乍一看似乎有很多工作,但我不确定优雅是否适用。
我们的想法是在interp
循环中使用lapply
来浏览感兴趣的后缀,并为每个匹配的变量对设置一个函数。
为避免对后缀进行硬编码,您可以将它们从数据集中拉出来。这适用于您所拥有的简单情况,但如果您的实际数据更复杂,可能需要更多考虑。
suffix = unique(sub(".*\\.", "", names(y)))
suffix
[1] "foo" "bar" "baz"
现在循环,在'+'(x, y)
中创建简单函数x + y
(又名interp
)。 x
和y
的变量通过paste
相应的后缀设置,全部包含在as.name
中。
dots = lapply(suffix,
function(suff) interp(~'+'(x, y),
x = as.name(paste("a", suff, sep = ".")),
y = as.name(paste("b", suff, sep = "."))))
dots
[[1]]
~a.foo + b.foo
<environment: 0x036bf4b8>
[[2]]
~a.bar + b.bar
<environment: 0x036c189c>
[[3]]
~a.baz + b.baz
<environment: 0x036c4c14>
然后只需使用mutate_
列表dots
来计算新变量。
mutate_(y, .dots = dots)
感兴趣的列如下:
a.foo + b.foo a.bar + b.bar a.baz + b.baz
1 -2.7750933 2.2524274 0.52665909
2 -1.6001349 0.7894692 -0.13340202
3 0.8031004 1.1632274 0.46272597
4 -0.9941492 1.4346315 -0.06327656
5 -1.7558620 1.4079703 -1.14218434
6 -0.6322581 -1.5661146 1.40710596
7 0.4077698 -2.9227982 1.33316137
8 -0.2664580 1.5139438 1.95130283
9 -0.4476210 -0.7926471 -0.44932288
10 -0.6217235 -1.2043056 -0.19059357
要获取新名称,您需要添加使用setNames
,再次使用paste
根据suffix
向量创建名称。
mutate_(y, .dots = setNames(dots, paste("z", suffix, sep = ".")))
新栏目:
z.foo z.bar z.baz
1 -2.7750933 2.2524274 0.52665909
2 -1.6001349 0.7894692 -0.13340202
3 0.8031004 1.1632274 0.46272597
4 -0.9941492 1.4346315 -0.06327656
5 -1.7558620 1.4079703 -1.14218434
6 -0.6322581 -1.5661146 1.40710596
7 0.4077698 -2.9227982 1.33316137
8 -0.2664580 1.5139438 1.95130283
9 -0.4476210 -0.7926471 -0.44932288
10 -0.6217235 -1.2043056 -0.19059357
答案 1 :(得分:0)
正如@aosmith所提到的,您可以将lazyeval::interp
结合使用以dplyr
结尾的_
函数进行解决方案的非标准评估,参见vignette("nse")
)帮助你。如果您想要更加通用而不必对+
操作进行硬编码(也许您有很多要汇总的列?),我还会在contains
中使用select
来申请直接将您的函数添加到所有相关列:
require(lazyeval)
suffix = unique(gsub(".*\\.", "", names(y)))
myNewColsValues = lapply(suffix,
function(pattern) interp(~ select(y, contains(patt))
%>% rowSums,
patt=pattern) )
y %>% mutate_( .dots = setNames(myNewColsValues, paste0('z.', suffix)) )