从数据框中的其他行提取和使用信息?

时间:2018-11-21 23:56:14

标签: r

所以我有一个如下数据框:

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的情况下如何解决此问题。

1 个答案:

答案 0 :(得分:1)

agefriend1作为索引,对列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是字符串。

如果列idfriend*是字符串而不是数字,则用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)