R 将前3个值保持在一行中,将其他所有值更改为NA
使用mtcars实现再现性 (这是一个行操作)。我想根据它们的大小将3个值保持在一行中(因此,基本上前3个值将具有值,其余所有值都更改为NA) 我尝试使用pivot_将数据转换为长数据,然后进行过滤,但问题是我想再次转换为宽数据,因为我想保留数据的结构R 将前3个值保持在一行中,将其他所有值更改为NA,r,dplyr,tidyverse,R,Dplyr,Tidyverse,使用mtcars实现再现性 (这是一个行操作)。我想根据它们的大小将3个值保持在一行中(因此,基本上前3个值将具有值,其余所有值都更改为NA) 我尝试使用pivot_将数据转换为长数据,然后进行过滤,但问题是我想再次转换为宽数据,因为我想保留数据的结构 mtcars %>% pivot_longer(cols = everything()) %>% group_by(name) %>% top_n(3) 3排mtcars上的样本输出 注意:在mtc
mtcars %>%
pivot_longer(cols = everything()) %>%
group_by(name) %>% top_n(3)
3排mtcars上的样本输出
注意:在mtcars中,所有3行的列名值都与非NA相同,但在原始数据集中则不同。(最好是tidyverse溶液)我知道您想要tidyverse溶液,但这是R底的一层:
t(应用(mtcars,1,功能(x){x[顺序(x)[1:(长度(x)-3)]mpg气缸显示高压拖动重量qsec vs调幅齿轮carb
#>马自达RX4 21.0北美160.0 110北美
#>马自达RX4 Wag 21.0北美160.0 110北美
#>Datsun 710 22.8 NA 108.0 93 NA NA NA
#>大黄蜂4路21.4北美258.0 110北美北美北美北美
#>大黄蜂运动约18.7 NA 360.0 175 NA NA NA
#>Valiant NA 225.0 105 NA 20.22 NA
#>除尘器360 NA 360.0 245 NA 15.84 NA NA
#>Merc 240D 24.4不适用146.7 62不适用
#>Merc 230 NA 140.8 95 NA 22.90 NA NA
#>Merc 280 19.2 NA 167.6 123 NA NA
#>Merc 280C NA 167.6 123 NA 18.90 NA NA
#>Merc 450SE NA 275.8 180 NA 17.40 NA
#>美世450SL NA 275.8 180 NA 17.60 NA
#>Merc 450SLC NA 275.8 180 NA 18.00 NA NA
#>卡迪拉克弗利特伍德NA 472.0 205 NA 17.98 NA NA NA
#>林肯大陆北美460.0 215北美17.82北美
#>克莱斯勒帝国NA 440.0 230 NA 17.42 NA NA
#>菲亚特128 32.4北美78.7 66北美
#>本田思域30.4 NA 75.7 52 NA NA NA
#>丰田花冠33.9 NA 71.1 65 NA NA
#>丰田科罗纳21.5 NA 120.1 97 NA NA NA
#>道奇挑战者NA 318.0 150 NA 16.87 NA NA
#>AMC标枪NA 304.0 150 NA 17.30 NA NA
#>Camaro Z28 NA 350.0 245 NA 15.41 NA NA
#>庞蒂亚克火鸟19.2 NA 400.0 175 NA NA NA
#>菲亚特X1-9 27.3 NA 79.0 66 NA
#>保时捷914-2 26.0 NA 120.3 91 NA NA NA NA NA
#>莲花欧罗巴30.4 NA 95.1 113 NA
#>福特Pantera L 15.8北美351.0 264北美北美
#>法拉利迪诺19.7 NA 145.0 175 NA NA
#>玛莎拉蒂宝来15.0北美301.0 335北美
#>沃尔沃142E 21.4不适用121.0 109不适用
您的总体思路是正确的。在使用slice_max()
并重新整形为宽数据之前,您可以先旋转到长数据并按行号分组:
library(dplyr)
library(tidyr)
library(tibble)
mtcars %>%
rowid_to_column() %>%
pivot_longer(-rowid) %>%
group_by(rowid) %>%
mutate(value = replace(value, !value %in% tail(value[order(value)], 3), NA)) %>%
pivot_wider(names_from = name, values_from = value)
# A tibble: 32 x 11
mpg cyl disp hp drat wt qsec vs am gear carb
<dbl> <lgl> <dbl> <dbl> <lgl> <lgl> <dbl> <lgl> <lgl> <lgl> <lgl>
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
库(dplyr)
图书馆(tidyr)
图书馆(tibble)
mtcars%>%
rowid_到_列()%>%
枢轴长度(-rowid)%>%
分组依据(rowid)%>%
变异(值=替换(值,!值%在%tail中(值[顺序(值)],3),NA))%>%
枢轴(名称从=名称,值从=值)
#一个tibble:32x11
mpg气缸显示hp drat wt qsec与am齿轮carb
1 21 NA 160 110 NA NA NA NA NA NA
2 21 NA 160 110 NA NA NA NA NA
3 22.8 NA 108 93 NA NA NA NA
4 21.4 NA 258 110 NA NA NA
5 18.7 NA 360 175 NA NA NA NA NA
6钠225钠105钠20.2钠
7 NA 360 245 NA 15.8 NA NA NA
824.4不适用147.62不适用
9钠141.95钠22.9钠
10 19.2 NA 168.123 NA NA NA NA
#…还有22排
看到您对其他解决方案很好奇
在这里,我为您提供了一个更加面向的解决方案
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
你也可以写:
mtcars %>% pmap_dfr(function(...) c(...) %>% replace(rank(desc(.)) > 3, NA))
这三个点基本上汇集了您提供给函数的所有输入。我没有为每个输入编写变量,而是使用…
将它们全部包含在内
pmap
将列表列表或向量列表作为第一个参数。
在本例中,它采用data.frame,它实际上是相同长度的向量列表
然后,pmap
为函数提供列表中每个向量的第i个元素
…
截取所有这些第i个元素并c()
创建这些元素的唯一向量
函数本身将以与公认的解决方案非常相似的方式替换该向量中的NAs。我使用了rank
,因为在我看来它更易于阅读,但我想这是一个风格问题
pmap
始终返回一个列表。也就是说,您可以使用pmap\u dfr
来返回数据帧。具体来说,您希望通过将最终结果的每个向量绑定为行来创建数据帧(这解释了末尾的r
)
查看?pmap
了解更多信息。一个dplyr
选项可以是:
mtcars %>%
rowwise() %>%
mutate(temp = list(tail(sort(c_across(everything())), 3))) %>%
ungroup() %>%
mutate(across(everything(), ~ replace(.x, !.x %in% unlist(temp), NA))) %>%
select(-temp)
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 22.8 NA 141. 95 NA NA 22.9 NA NA NA NA
10 19.2 NA 168. 123 NA NA NA NA NA NA NA
A数据表
完整性解决方案:
DT <- as.data.table(mtcars)
DT[,
{
t3 <- sort(unlist(.SD), decreasing = TRUE)[1:3]
lapply(.SD, function(x) if (x %in% t3) x else NA_real_)
},
by = seq_len(nrow(DT))]
# seq_len mpg cyl disp hp drat wt qsec vs am gear carb
# 1: 1 21.0 NA 160.0 110 NA NA NA NA NA NA NA
# 2: 2 21.0 NA 160.0 110 NA NA NA NA NA NA NA
# 3: 3 22.8 NA 108.0 93 NA NA NA NA NA NA NA
# 4: 4 21.4 NA 258.0 110 NA NA NA NA NA NA NA
# 5: 5 18.7 NA 360.0 175 NA NA NA NA NA NA NA
# 6: 6 NA NA 225.0 105 NA NA 20.22 NA NA NA NA
# ...
DT谢谢你指导我找到这个解决方案,从两个答案中都学到了很多东西为什么是slice_max而不是top_n,会有什么不同吗?top_n()
已经被取代了
mtcars %>%
pmap_dfr(~ replace(c(...), !c(...) %in% tail(sort(c(...)), 3), NA))
DT <- as.data.table(mtcars)
DT[,
{
t3 <- sort(unlist(.SD), decreasing = TRUE)[1:3]
lapply(.SD, function(x) if (x %in% t3) x else NA_real_)
},
by = seq_len(nrow(DT))]
# seq_len mpg cyl disp hp drat wt qsec vs am gear carb
# 1: 1 21.0 NA 160.0 110 NA NA NA NA NA NA NA
# 2: 2 21.0 NA 160.0 110 NA NA NA NA NA NA NA
# 3: 3 22.8 NA 108.0 93 NA NA NA NA NA NA NA
# 4: 4 21.4 NA 258.0 110 NA NA NA NA NA NA NA
# 5: 5 18.7 NA 360.0 175 NA NA NA NA NA NA NA
# 6: 6 NA NA 225.0 105 NA NA 20.22 NA NA NA NA
# ...