看到您对其他解决方案很感兴趣...
这里我给您留下了一个更加以tidyverse
为导向的解决方案。
library(purrr)
library(dplyr)
mtcars %>% pmap_dfr(~c(...) %>% replace(rank(desc(.)) > 3, NA))
#> # A tibble: 32 x 11
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 21 NA 160 110 NA NA NA NA NA NA NA
#> 2 21 NA 160 110 NA NA NA NA NA NA NA
#> 3 22.8 NA 108 93 NA NA NA NA NA NA NA
#> 4 21.4 NA 258 110 NA NA NA NA NA NA NA
#> 5 18.7 NA 360 175 NA NA NA NA NA NA NA
#> 6 NA NA 225 105 NA NA 20.2 NA NA NA NA
#> 7 NA NA 360 245 NA NA 15.8 NA NA NA NA
#> 8 24.4 NA 147. 62 NA NA NA NA NA NA NA
#> 9 NA NA 141. 95 NA NA 22.9 NA NA NA NA
#> 10 19.2 NA 168. 123 NA NA NA NA NA NA NA
#> # ... with 22 more rows
作为一个概念,它类似于 `base` R 解决方案,但它应该(或至少尝试)更加“函数式”,并且希望更容易阅读。即使所选择的解决方案看起来非常好。
编辑。
回答您关于更多信息的评论...
应该知道 `~` 帮助您编写更紧凑的匿名函数。
而不是:
mtcars %>% pmap_dfr(~c(...) %>% replace(rank(desc(.)) > 3, NA))
你也可以这样写:
mtcars %>% pmap_dfr(function(...) c(...) %>% replace(rank(desc(.)) > 3, NA))
这三个点可以将您提供给函数的所有输入聚合在一起。与为每个输入编写变量不同,我使用...
将它们全部包括在内。
pmap
将列表或向量列表作为第一个参数。在这种情况下,它接受一个数据框,实际上是一个长度相同的向量列表。
然后,pmap
将向列表中每个向量的第i个元素提供给函数。
...
截取所有这些第i个元素,并使用c()
创建这些元素的唯一向量。
该函数本身仅以非常类似于被接受的解决方案的方式替换该向量中的NA值。我使用rank
,因为它对我来说更容易阅读,但我想这是一个风格问题。
pmap
始终返回列表。 这就是您可以使用pmap_dfr
返回数据框的原因。具体而言,您要通过将最终结果的每个向量绑定为行来创建数据框(这解释了末尾的r
)。
查看?pmap
获取更多信息。
t(apply(mtcars, 1, function(x) {x[rank(-x) > 3] <- NA; x}))
- s_baldur