我正在用R编写非常干燥的dplyr链。我需要在数据框中的很多列上调用dplyr::mutate() and dplyr::percent_rank()
函数,对于我每个电话没有一行代码很有帮助。我需要为其计算百分位数的数据框列具有以下模式:
regions <- c("atr2", "sht2", "mid2", "lng2", "all2", "sht3", "lng3", "all3")
suffixes <- c("Made", "Att", "AttFreq", "Pct")
for(i in regions) {
for(j in suffixes) {
print(paste0(i, j))
}
}
在上面的示例中,我需要8 * 4 == 32
个不同的百分位数列。所有32个初始列atr2Made
,atr2Att
等都已经在我的数据框中。为了计算百分位数,我一直在做以下事情:
pctile.lineup.data <- pctile.lineup.data %>%
dplyr::group_by(season) %>%
# dplyr::group_by(season, homeConfId) %>%
dplyr::mutate(atr2MadeRankNcaa = round(100 * dplyr::percent_rank(atr2Made))) %>%
dplyr::mutate(atrAttRankNcaa = round(100 * dplyr::percent_rank(atr2Att))) %>%
dplyr::mutate(atr2AttFreqRankNcaa = round(100 * dplyr::percent_rank(atr2AttFreq))) %>%
dplyr::mutate(atr2PctRankNcaa = round(100 * dplyr::percent_rank(atr2Pct))) %>%
dplyr::mutate(sht2MadeRankNcaa = round(100 * dplyr::percent_rank(sht2Made))) %>%
dplyr::mutate(shtAttRankNcaa = round(100 * dplyr::percent_rank(sht2Att))) %>%
dplyr::mutate(sht2AttFreqRankNcaa = round(100 * dplyr::percent_rank(sht2AttFreq))) %>%
dplyr::mutate(sht2PctRankNcaa = round(100 * dplyr::percent_rank(sht2Pct))) %>%
dplyr::mutate(mid2MadeRankNcaa = round(100 * dplyr::percent_rank(mid2Made))) %>%
dplyr::mutate(midAttRankNcaa = round(100 * dplyr::percent_rank(mid2Att))) %>%
dplyr::mutate(mid2AttFreqRankNcaa = round(100 * dplyr::percent_rank(mid2AttFreq))) %>%
dplyr::mutate(mid2PctRankNcaa = round(100 * dplyr::percent_rank(mid2Pct))) %>%
... %>%
dplyr::ungroup()
我不仅需要32个不同的mutate()
函数,还需要为2个不同的group_by()
运行两次此代码(请参阅第二个注释掉)。有没有比64行代码更好的方法?我有一个单独的dataram,它具有21个区域而不是8个区域,具有相同的4个后缀和相同的2个group_by()s,因此计算这些百分位数需要21 * 4 * 2 == 168行代码。这不是DRY-请帮忙!
编辑:显然,我正在研究mutate_at
,但是对mutate的_at
版本不是很熟悉/不熟悉。我的数据框中除了这32列之外还有其他列,因此我认为mutate_all
不起作用。
答案 0 :(得分:2)
这正是dplyr::mutate_at
的用途。从一些示例数据开始:
df <- data.frame(name = LETTERS[1:5],
item1 = rnorm(5, mean=2),
item2 = rnorm(5, mean=5),
item3 = rnorm(5, mean=7))
*_at
函数接受2个参数:
.vars
参数,它接受dplyr::select
使用的选择器功能。在这种情况下,我们使用one_of
提供变量列表,但是如果变量有模式,可以使用contains
或starts_with
简化此过程.funs
参数,我们将函数应用于这些列中的每列。 请注意,为了使这些参数正常工作,必须将这些参数分别包装在vars
和funs
函数中:
df %>%
mutate_at(.vars = vars(one_of('item1', 'item2')),
.funs = funs(rounded = round(100 * percent_rank(.)))
name item1 item2 item3 item1_rounded item2_rounded
1 A 3.801373 5.701111 9.871991 100 75
2 B 2.264733 5.730916 8.558700 25 100
3 C 3.432726 5.623918 7.359317 75 50
4 D 2.137491 5.286736 7.996114 0 25
5 E 3.227416 5.269252 6.588257 50 0
由于.funs
中的函数被命名为(rounded = ...
,所以该操作的结果被制成新变量,后缀为。如果未命名,则所选变量将被自己修改(即item1
和item2
将被四舍五入)