所以我有一个如下数据框:
id age friend1 friend2
01 15 02 05
02 23 01 05
03 51 04
04 41 03
05 33 01 02
如何计算朋友的平均年龄并创建一个存储此信息的新列?因此理想情况下看起来像这样:
id age friend1 friend2 AvgAgeF
01 15 02 05 28
02 23 01 05 24
03 51 04 41
04 41 03 51
05 33 01 02 19
当前,我可以运行以下代码来做到这一点:
inx <- grep("friend", names(dat))
tmp <- sapply(inx, function(i) dat$age[dat[[i]]])
dat$AvgAgeF <- rowMeans(tmp, na.rm = TRUE)
但是,当人们的“ id”不正确或根本不是数字时,例如以下示例:
dat <- read.table(text = "
id age friend1 friend2
Bob 15 Jack Sam
Jack 23 Sam Bob
Sam 51 Bob Jack
Sara 41 Henry NA
Henry 33 Sara NA
", header = TRUE)
该代码似乎无法正确处理,导致产生了下表(在这种情况下,除Sam的AvgAgeF之外的所有代码都不正确):
id age friend1 friend2 AvgAgeF
1 Bob 15 Jack Sam 51
2 Jack 23 Sam Bob 28
3 Sam 51 Bob Jack 19
4 Sara 41 Henry <NA> 23
5 Henry 33 Sara <NA> 33
在不将名称更改为数字ID的情况下如何解决此问题。
答案 0 :(得分:1)
用age
和friend1
作为索引,对列friend2
进行子集设置,然后cbind
生成结果向量。现在,它是对rowMeans
的简单调用。
tmp <- with(dat, cbind(age[friend1], age[friend2]))
dat$AvgAgeF <- rowMeans(tmp, na.rm = TRUE)
rm(tmp)
dat
# id age friend1 friend2 AvgAgeF
#1 1 15 2 5 28
#2 2 23 1 5 24
#3 3 51 4 NA 41
#4 4 41 3 NA 51
#5 5 33 1 2 19
编辑。
如果friend*
列的数量不确定,则必须遵循另一种策略。
首先是一个数据集,从问题数据开始。
set.seed(1234)
tmp <- matrix(sample(c(NA, 1:5), 20, TRUE), nrow = 5)
colnames(tmp) <- paste0("friend", 3:6)
dat <- cbind(dat, tmp)
现在,使用grep
来获取friend
列。
inx <- grep("friend", names(dat))
tmp <- sapply(inx, function(i) dat$age[dat[[i]]])
dat$AvgAgeF <- rowMeans(tmp, na.rm = TRUE)
最终清理。
rm(tmp)
编辑2-id
是字符串。
如果列id
和friend*
是字符串而不是数字,则用age
索引列match
。
inx <- grep("friend", names(dat2))
tmp <- sapply(inx, function(i) {
x <- as.character(dat2[[i]])
y <- as.character(dat2$id)
dat2$age[match(x, y)]
})
dat2$AvgAgeF <- rowMeans(tmp, na.rm = TRUE)
rm(tmp)
dat2
# id age friend1 friend2 AvgAgeF
#1 Bob 15 Jack Sam 37
#2 Jack 23 Sam Bob 33
#3 Sam 51 Bob Jack 19
#4 Sara 41 Henry <NA> 33
#5 Henry 33 Sara <NA> 41
数据。
dat <- read.table(text = "
id age friend1 friend2
01 15 02 05
02 23 01 05
03 51 04 NA
04 41 03 NA
05 33 01 02
", header = TRUE)
dat2 <- read.table(text = "
id age friend1 friend2
Bob 15 Jack Sam
Jack 23 Sam Bob
Sam 51 Bob Jack
Sara 41 Henry NA
Henry 33 Sara NA
", header = TRUE)