问题描述
给出如下数据框:
df <- data.frame(ID = seq(1,8),rank1 = c("apple","NA","banana","kiwi","peach","grape"),rank2 = c('mango','NA','date','grape','kiwi','apple','pear','NA'),rank3 = c('kiwi','apple ','peach','banana','mango','NA'))
ID rank1 rank2 rank3
1 1 apple mango kiwi
2 2 NA NA NA
3 3 banana date apple
4 4 kiwi grape peach
5 5 peach kiwi banana
6 6 kiwi apple NA
是否可以将这些值转换为变量并根据其等级为它们分配一个值?
我想要这样的输出:
ID apple mango kiwi banana date grape peach pear
1 1 rank1 rank2 rank3 NA NA NA NA NA
2 2 NA NA NA NA NA NA NA NA
3 3 rank3 NA NA rank1 rank2 NA NA NA
4 4 NA NA rank1 NA NA rank2 rank3 NA
5 5 NA NA rank2 rank3 NA NA rank1 NA
6 6 rank2 NA rank1 NA NA NA NA NA
如何使用以下公式将权重分配给排名位置:n-r + 1(n =标准数量,r =排名位置)?
解决方法
一种方法是将原始数据帧的形状调整为较长的格式,然后将其更改为较宽的格式以切换变量。
library(tidyr)
library(dplyr)
#pivot longer
dfl <- pivot_longer(df,starts_with("rank"),names_to="rank",values_to = "fruit")
#clean up data
dfl$fruit <- trimws(dfl$fruit)
#dfl <- dfl[dfl$fruit != "NA",] #optional
#reshape wider
pivot_wider(dfl,ID,names_from = "fruit",values_from = "rank",values_fn = first)
# # A tibble: 8 x 10
# ID apple mango kiwi `NA` banana date grape peach pear
# <int> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
# 1 1 rank1 rank2 rank3 NA NA NA NA NA NA
# 2 2 NA NA NA rank1 NA NA NA NA NA
# 3 3 rank3 NA NA NA rank1 rank2 NA NA NA
# 4 4 NA NA rank1 NA NA NA rank2 rank3 NA
# 5 5 NA NA rank2 NA rank3 NA NA rank1 NA
# 6 6 rank2 NA rank1 rank3 NA NA NA NA NA
# 7 7 NA rank3 rank1 NA NA NA NA NA rank2
# 8 8 NA NA NA rank2 NA NA rank1 NA NA
由于我正在first
函数中使用pivot_wider
函数。如果ID内有多个(如原始数据的第二行一样),则选择第一个实例。
注意:“ NA”列将需要删除。
,我相信,这个dplyr/tidyr
管道计算的是排名,而不是问题中引用的权重。
library(tidyverse)
df %>%
pivot_longer(
cols = starts_with('rank'),names_to = 'rank',values_to = 'fruit'
) %>%
mutate(rank = as.integer(sub('^rank','',rank)),fruit = trimws(fruit)) %>%
filter(!is.na(fruit),fruit != 'NA') %>%
pivot_wider(
id_cols = ID,names_from = fruit,values_from = rank
)
## A tibble: 7 x 9
# ID apple mango kiwi banana date grape peach pear
# <int> <int> <int> <int> <int> <int> <int> <int> <int>
#1 1 1 2 3 NA NA NA NA NA
#2 3 3 NA NA 1 2 NA NA NA
#3 4 NA NA 1 NA NA 2 3 NA
#4 5 NA NA 2 3 NA NA 1 NA
#5 6 2 NA 1 NA NA NA NA NA
#6 7 NA 3 1 NA NA NA NA 2
#7 8 NA NA NA NA NA 1 NA NA
,
这是使用stack
+ reshape
dfout <- reshape(
subset(
cbind(stack(df[-1]),id = df$ID),values != "NA"
),direction = "wide",idvar = "id",timevar = "values"
)
dfout <- setNames(dfout,gsub("ind\\.","",names(dfout)))
给出
id apple banana kiwi peach grape mango date pear apple
1 1 rank1 <NA> rank3 <NA> <NA> rank2 <NA> <NA> <NA>
3 3 <NA> rank1 <NA> <NA> <NA> <NA> rank2 <NA> rank3
4 4 <NA> <NA> rank1 rank3 rank2 <NA> <NA> <NA> <NA>
5 5 <NA> rank3 rank2 rank1 <NA> <NA> <NA> <NA> <NA>
6 6 rank2 <NA> rank1 <NA> <NA> <NA> <NA> <NA> <NA>
7 7 <NA> <NA> rank1 <NA> <NA> rank3 <NA> rank2 <NA>
8 8 <NA> <NA> <NA> <NA> rank1 <NA> <NA> <NA> <NA>