【发布时间】:2018-07-03 22:36:53
【问题描述】:
我经常有一个数据框,里面包含一个数值变量和一个分类变量,我想根据分类变量对数值变量进行拆分,进行一些操作,然后以数据框的形式重新组合起来。该操作取决于一个类别中数值向量的整个部分,并且有时会返回一个不同长度的向量。我知道如何以一种丑陋的方式做到这一点(见
下面的示例),但这似乎是一种常见的操作,所以我想知道是否有一种我不知道的更简单的方法。我特别想知道是否有使用tidyverse 的解决方案。
这是我所说的一个例子。
df = data.frame(y=1:10, g=rep(c("a", "b"), each=5))
假设我想将变量 y 标准化为介于 0 和 1 之间对于分类变量的每个级别。这是一个通用的方法:
do.call(
rbind,
lapply(unique(df$g),
function(level) {
y.current = df$y[df$g==level]
## perform some operation
y.new = (y.current-min(y.current))/
(max(y.current)-min(y.current))
return(data.frame(y=y.new,
g=level))
}
)
)
这需要大量输入,而且可读性不强。有没有更好的办法?
编辑:感谢您的出色回答。我唯一仍然感兴趣的是使用tidyverse 执行此操作的完全通用方法。如果我们将示例更改为数值向量的大小减小但大于 1 的操作,则 group_by/mutate/summarize 组合不起作用。例如,假设我想删除每个组中的最大值。我可以的
library(dplyr)
df = data.frame(y=1:10, g=rep(c("a", "b"), each=5))
trans_df = df %>%
group_by(g) %>%
do(y=.$y[-which.max(.$y)])
转换后的数据框trans_df 具有每个级别一个观察值的分组变量,并且转换后的变量作为分组变量每个级别的列表。我可以使用 base R 将其置于原始格式中
data.frame(g=rep(trans_df$g, times=sapply(trans_df$y, length)),
y=do.call(c, trans_df$y))
但是我怎样才能使用tidyverse呢?
【问题讨论】: