我有一个数据框,其中包含重复采样个体和活着天数的数据。有些人每天都没有活着的样本。我希望将数据从面向行(每个单独和一天存活为一行)移动到面向列(一行为一个人,每列保存每天的数据)。
然而,当一个人在第一个DF中没有某一天活着的时候,我正在为此运行的代码会出错,因为在第二个DF中有一个列存活。我没有找到一个很好的方法来测试第一个DF中是否存在行和值,它使值为长度为0的数字(即数字(0))并对这样的变量执行逻辑测试不会提供逻辑答案(O或1),它只产生逻辑(0)。
以下是我正在尝试做的简化示例。我知道可能有其他方法可以处理我正在做的一些较大的数据移动,但是如果可能的话,我希望这样做。当个人= B且dayAlive = 2时,下面的代码将被卡住,因为该个人没有dayAlive = 2。我希望能够测试没有这样的行,然后在第二个数据帧单元格中插入一个NA或其他东西。
# Initialize data in row format in first data fram:
v1<-c("A",1,1.3)
v2<-c("A",2,1.8)
v3<-c("A",3,2.4)
v4<-c("B",1,0.8)
v5<-c("B",3,1.7)
first_DF<-data.frame(matrix(c(v1,v2,v3,v4,v5),ncol=3, nrow=5,byrow=TRUE,dimnames=list(NULL,c("Individual","DayAlive","Length"))), stringsAsFactors=FALSE)
# Convert to column format in second data frame:
individual_IDs<-unique(first_DF$"Individual")
days_alive<-unique(first_DF$"DayAlive")
# Initialize second DF by subsetting a single row for each individual from the first DF
second_DF<-data.frame(first_DF[which(first_DF$"Individual" %in% individual_IDs & first_DF$"DayAlive" %in% 1),1], stringsAsFactors=FALSE)
names(second_DF)<-"Individual"
initial_DF_width<-dim(second_DF)[2]
# Move 'Length' data into the columns as each 'day alive' column is created:
for(i in 1:length(days_alive)){
current_day<-days_alive[i]
second_DF<-cbind(second_DF,matrix(ncol=1, nrow=nrow(second_DF),dimnames=list(NULL,paste("Day ",current_day," Length"))))
for(j in 1:length(individual_IDs)){
current_individualID<-individual_IDs[j]
length<-first_DF[which(first_DF$"Individual" %in% current_individualID & first_DF$"DayAlive" %in% current_day),"Length"]
second_DF[j,i+initial_DF_width]<-length
}
}
这是它抛出的错误:
[<-.data.frame
中的错误(*tmp*
,j,i + initial_DF_width,value = character(0)): 替换的长度为零
(在我的真实代码中,我已经将数据转换为数字但没有在这里打扰)。
答案 0 :(得分:2)
您应该查看reshape2
包。试试这个:
library('reshape2')
dcast(first_DF, Individual ~ DayAlive)
# Individual 1 2 3
# 1 A 1.3 1.8 2.4
# 2 B 0.8 <NA> 1.7
既然你说你想按照自己的方式去做,我也编辑了你的嵌套循环。但是我不建议这样做。大多数人会告诉你R中的嵌套循环通常不是最好的主意,在这种情况下肯定是正确的。
for(i in 1:length(days_alive)){
current_day<-days_alive[i]
second_DF<-cbind(second_DF,matrix(ncol=1, nrow=nrow(second_DF),dimnames=list(NULL,paste("Day ",current_day," Length"))))
for(j in 1:length(individual_IDs)){
current_individualID<-individual_IDs[j]
# I changed "length" to "length2" to avoid confusion with the
# function length(). You also don't need which() here.
length2 <- first_DF[first_DF$Individual %in% current_individualID
& first_DF$DayAlive %in% current_day, "Length"]
if (length(length2) > 0) {
second_DF[j, i + initial_DF_width] <- length2
} else {
second_DF[j, i + initial_DF_width] <- NA
}
}
}