如何测试数据帧中缺少的行/值以帮助转置其中的一部分?

时间:2014-07-18 21:01:21

标签: r dataframe missing-data reshape2

我有一个数据框,其中包含重复采样个体和活着天数的数据。有些人每天都没有活着的样本。我希望将数据从面向行(每个单独和一天存活为一行)移动到面向列(一行为一个人,每列保存每天的数据)。

然而,当一个人在第一个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)):    替换的长度为零

(在我的真实代码中,我已经将数据转换为数字但没有在这里打扰)。

1 个答案:

答案 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
    }
  }
}