【问题标题】:How to assign number of repeats to dataframe based on elements of an identifying vector in R?如何根据 R 中识别向量的元素为数据帧分配重复次数?
【发布时间】:2011-10-06 01:39:36
【问题描述】:

我有一个数据框,其中的个人分配了一个文本 id,该文本 id 将地名与个人 id 连接起来(请参阅下面的数据)。最终,我需要将数据集从“长”转换为“宽”(例如,使用“重塑”),以便每个人只包含一行。为了做到这一点,我需要分配一个“时间”变量,reshape 可以使用它来识别随时间变化的协变量等。我有(可能是坏的)代码来为重复最多两次的个人执行此操作,但需要能够识别多达 18 次重复出现。如果我删除哈希前面的行,下面的代码可以正常工作,但最多只能识别两次重复。如果我留下那条线(这对于重复两次以上的个人来说似乎是必要的),R 会窒息,给出以下错误(可能是因为第一个个人只重复了两次):

Error in if (data$uid[i] == data$uid[i - 2]) { : 
  argument is of length zero

有人可以帮忙吗?提前致谢!

place <- rep("ny",10)
pid <- c(1,1,2,2,2,3,4,4,5,5)
uid<- paste(place,pid,sep="")
time <- rep(0,10)
data <- cbind(uid,time)
data <- as.data.frame(data)
data$time <- as.numeric(data$time)

#bad code
data$time[1] <- 1 #need to set first so that loop doesn't go to a row that doesn't exist     (i.e., row 0)
for (i in 2:NROW(data)){
    data$time[i] <- 1 #set first occurrence to 1
    if (data$uid[i] == data$uid[i-1]) {data$time[i] <- 2} #set second occurrence to 2, etc.
    #if (data$uid[i] == data$uid[i-2]) {data$time[i] <- 3}
    i <- i+1
}

【问题讨论】:

    标签: r vector elements repeat reshape


    【解决方案1】:

    目前尚不清楚您要做什么,但我认为您是说您需要为每一行每个唯一的uid 创建一个时间索引。对吗?

    如果是这样,试一试

    library(plyr)
    ddply(data, "uid", transform, time = seq_along(uid))
    

    会给你类似的东西:

       uid time
    1  ny1    1
    2  ny1    2
    3  ny2    1
    4  ny2    2
    5  ny2    3
    ....
    

    【讨论】:

    • 这对我不起作用。是不是哪里有错别字?
    【解决方案2】:

    这是你的想法吗?

    > d <- data.frame(uid = paste("ny",c(1,2,1,2,2,3,4,4,5,5),sep=""))
    > out <- do.call(rbind, lapply(split(d, d$uid), function(x) {x$time <- 1:nrow(x); x}))
    > rownames(out) <- NULL
    > out
       uid time
    1  ny1    1
    2  ny1    2
    3  ny2    1
    4  ny2    2
    5  ny2    3
    6  ny3    1
    7  ny4    1
    8  ny4    2
    9  ny5    1
    10 ny5    2
    

    【讨论】:

      【解决方案3】:

      使用您的数据框设置:

      place <- rep("ny",10)
      pid <- c(1,1,2,2,2,3,4,4,5,5)
      uid<- paste(place,pid,sep="")
      time <- rep(0,10)
      data <- cbind(uid,time)
      data <- as.data.frame(data)
      

      你可以使用:

      data$time <- sequence(table(data$uid))
      data
      

      获得:

      > data
         uid time
      1  ny1    1
      2  ny1    2
      3  ny2    1
      4  ny2    2
      5  ny2    3
      6  ny3    1
      7  ny4    1
      8  ny4    2
      9  ny5    1
      10 ny5    2
      

      注意:您的 data.frame 必须首先按 uid 排序才能正常工作。

      【讨论】:

      • 不用担心。请记住更新您的首选答案,并由您决定检查其下方的勾号,以便人们可以看到最有用的答案。它还有助于您的评分选择首选答案。
      【解决方案4】:

      在大型数据集上尝试了上述解决方案后,我决定为此编写自己的循环。这非常非常耗时,并且仍然需要将数据分解为 50k 元素的向量,但它最终确实奏效了:

      system.time( for(i in 2:length(data$uid)) {
      if(data$uid[i]==data$uid[i-1]) data$repeats[i] <- data$repeats[i-1]+1
        if ((i %% 1000)== 0) { #helps to keep track of how far the loop has gotten
          print(i) }
          i+1
      }
      )
      

      感谢大家的帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-27
        • 2020-06-21
        • 1970-01-01
        • 1970-01-01
        • 2019-11-09
        • 2023-03-30
        • 1970-01-01
        相关资源
        最近更新 更多