将子集的矢量值替换为子集的平均值
我有一个有点凌乱的数据框,其中的主题排名,但有些与排名并列。将子集的矢量值替换为子集的平均值
subj<-c("A","B","C,D,E","C,D,E","C,D,E","F","G,H","G,H","I")
rank<-c(1,2,3,4,5,6,7,8,9)
df<-data.frame(rank,subj)
df
rank subj
1 1 A
2 2 B
3 3 C,D,E
4 4 C,D,E
5 5 C,D,E
6 6 F
7 7 G,H
8 8 G,H
9 9 I
如果个人被捆绑在一起,我需要将他们的排名表达为平局的平均值。喜欢的东西
n.rank n.subj
1 1.0 A
2 2.0 B
3 4.0 C
4 4.0 D
5 4.0 E
6 6.0 F
7 7.5 G
8 7.5 H
9 9.0 I
我一直在使用strngsplit()
和队伍命名列表的元素试过,但我最终似乎同样难以对付的数据帧。
a<-strsplit(as.character(df$subj),",")
names(a)<-df$rank
b<-melt(a)
colnames(b)<-c("n.subj","n.rank")
b[1:10,]
n.subj n.rank
1 A 1
2 B 2
3 C 3
4 D 3
5 E 3
6 C 4
7 D 4
8 E 4
9 C 5
10 D 5
我也达到一个死胡同,当我用gregexpr()
和regmatches()
,试图找出需要进行平均行列。
m<-gregexpr(",+",df$subj)
df$no.avg<-melt(lapply(regmatches(df$subj, m),length))[,1]+1
df
rank subj no.avg
1 1 A 1
2 2 B 1
3 3 C,D,E 3
4 4 C,D,E 3
5 5 C,D,E 3
6 6 F 1
7 7 G,H 2
8 8 G,H 2
9 9 I 1
那里有什么创意解决方案吗?非常感谢。
这是我的尝试。我首先计算平均排名,然后将同一排名的主题分成若干行。
library(tidyverse)
options(stringsAsFactors = FALSE)
subj <- c("A", "B", "C,D,E", "C,D,E", "C,D,E", "F", "G,H", "G,H", "I")
rank <- c(1, 2, 3, 4, 5, 6, 7, 8, 9)
df <- data.frame(rank, subj)
df %>%
group_by(subj) %>%
summarise(rank = mean(rank)) %>%
rowwise() %>%
do(tibble(subj = unlist(strsplit(.$subj, ",")), rank = .$rank)) %>%
ungroup()
输出:
# A tibble: 9 × 2
subj rank
* <chr> <dbl>
1 A 1.0
2 B 2.0
3 C 4.0
4 D 4.0
5 E 4.0
6 F 6.0
7 G 7.5
8 H 7.5
9 I 9.0
的另一种方法:
m <- aggregate(rank~subj, data=df, mean)
m <- apply(m, 1, function(x) data.frame(subj = unlist(strsplit(x[1], ",")), rank = x[2]))
m <- do.call(rbind, m)
rownames(m) <- NULL
m
输出:
subj rank
1 A 1.0
2 B 2.0
3 C 4.0
4 D 4.0
5 E 4.0
6 F 6.0
7 G 7.5
8 H 7.5
9 I 9.0
data.table
版本:
#library(data.table) #version 1.9.8
setDT(df)
df[, .(subj=unlist(strsplit(subj[1], ",")), rank=mean(rank)), by=subj][,-1]
# subj rank
#1: A 1.0
#2: B 2.0
#3: C 4.0
#4: D 4.0
#5: E 4.0
#6: F 6.0
#7: G 7.5
#8: H 7.5
#9: I 9.0
当我在示例脚本上运行'data.table'代码时,输出只是简单的'-1'。我对'data.table'不是很熟悉,所以我不确定问题出在哪里。 – gavago
@ user3166232尝试从最后删除'[,-1]'。你可能有不同版本的软件包,导致一些细微的差异 - 我在v1.9.8上。 – thelatemail
我的版本与splitstackshape
和aggregate
。逻辑是一样的,我们用逗号分割字符串并采用subj
的意思。
library(splitstackshape)
aggregate(rank~subj, cSplit(df, "subj", ",", "long"), mean)
# subj rank
#1 A 1.0
#2 B 2.0
#3 C 4.0
#4 D 4.0
#5 E 4.0
#6 F 6.0
#7 G 7.5
#8 H 7.5
#9 I 9.0
其中
cSplit(df, "subj", ",", "long")
给
# rank subj
# 1: 1 A
# 2: 2 B
# 3: 3 C
# 4: 3 D
# 5: 3 E
# 6: 4 C
# 7: 4 D
# 8: 4 E
# 9: 5 C
#10: 5 D
#11: 5 E
#12: 6 F
#13: 7 G
#14: 7 H
#15: 8 G
#16: 8 H
#17: 9 I
下面是使用tidyverse
另一种选择。该数据集是通过使用拆分separate_rows
,然后通过“SUBJ”分组的“SUBJ”列转换为“长”格式,得到“排名”
library(tidyverse)
separate_rows(df, subj) %>%
group_by(subj) %>%
summarise(rank = mean(rank))
# A tibble: 9 × 2
# subj rank
# <chr> <dbl>
#1 A 1.0
#2 B 2.0
#3 C 4.0
#4 D 4.0
#5 E 4.0
#6 F 6.0
#7 G 7.5
#8 H 7.5
#9 I 9.0
最终的
mean
,我没有使用这个脚本因为我不活在'tidyverse'中,但是按平均排列顺序的逻辑首先解决了问题。非常感谢。 – gavago@gavago不客气。我添加了另一种不需要'tidyverse'或'dplyr'的方法。 – kitman0804