代码之家  ›  专栏  ›  技术社区  ›  little girl

将非连续索引更改为连续索引

r
  •  1
  • little girl  · 技术社区  · 7 年前

    我有这样的数据:

       doc_id sentence_id token_id head_token_id
    1    doc1           1        1             0
    2    doc1           1        2             1
    3    doc1           1        3             1
    4    doc1           1        4             3
    5    doc1           1        5             4
    6    doc1           1        6             1
    7    doc1           2        1             2
    8    doc1           2        2             0
    9    doc1           2        3             2
    10   doc1           2        4             3
    11   doc1           2        5             2
    12   doc2           1        1             0
    13   doc2           1        2             1
    14   doc2           1        3             4
    15   doc2           1        4             1
    

    连续的例如,“head\u token\u id”的值 doc_id == "doc_1" sentence_id == 1 0, 1, 1, 3, 4, 1 . 我想将它们更改为连续值 0, 1, 1, 2, 3, 1 . 我想在每组“doc\u id”和“句子id”中这样做。

    head\u token\u id中的数字0和1始终相同。但其余数字可能相同或不同。In取决于这个句子中是否存在前面的数字。例如

       doc_id sentence_id token_id head_token_id new_head_token_id
    4    doc1           1        4             3                 2
    

    在这里,我们看到3从head\u token\u id更改为2,因为在head\u token\u id列中的这个句子(句子1,doc 1)中没有数字2。我试图删除“数字跳跃”。

       doc_id sentence_id token_id head_token_id new_head_token_id
    1    doc1           1        1             0                 0
    2    doc1           1        2             1                 1
    3    doc1           1        3             1                 1
    4    doc1           1        4             3                 2
    5    doc1           1        5             4                 3
    6    doc1           1        6             1                 1
    7    doc1           2        1             2                 1
    8    doc1           2        2             0                 0
    9    doc1           2        3             2                 1
    10   doc1           2        4             3                 2
    11   doc1           2        5             2                 1
    12   doc2           1        1             0                 0
    13   doc2           1        2             1                 1
    14   doc2           1        3             4                 2
    15   doc2           1        4             1                 1
    

    for (i in unique(df$doc_id)){
      for(j in unique(df$sentence_id){
        for(k in df$token_id){
          if(df$head_token_id[k] == 0){df$new_head_token_id[k] = 0} else
            if(df$head_token_id[k] == 1){df$new_head_token_id[k] = 1}
        }
      }
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Gregor Thomas    7 年前

    将变量视为一个因子,这种重新标记非常容易。然后我们可以强制它回到数值。我们使用的事实是 unique() 按发生顺序排列 .

    我们想在向量上做的运算 x

    as.numeric(as.character(
      factor(x, levels = unique(x), labels = seq_along(unique(x)) - 1)
    ))
    

    这将重新标记的唯一值 x 它们发生的顺序。这个 -1 使其从0开始,而不是从1开始。我们强迫回到数值。我们将把它变成一个函数:

    label0 = function(x) {
        as.numeric(as.character(
          factor(x, levels = unique(x), labels = seq_along(unique(x)) - 1)
        ))
    }
    

    dplyr ,但您可以使用 data.table , base::ave , base::by split; lapply; rbind 等。这些方法的示例以及更多信息可在R-FAQ上找到 Sum a variable by group ,您只想使用 label0 而不是 sum .

    library(dplyr)
    group_by(dat, doc_id, sentence_id) %>% mutate(new_head_token_id = label0(head_token_id))
    # # A tibble: 15 x 5
    # # Groups:   doc_id, sentence_id [3]
    #    doc_id sentence_id token_id head_token_id new_head_token_id
    #    <fctr>       <int>    <int>         <int>             <dbl>
    #  1   doc1           1        1             0                 0
    #  2   doc1           1        2             1                 1
    #  3   doc1           1        3             1                 1
    #  4   doc1           1        4             3                 2
    #  5   doc1           1        5             4                 3
    #  6   doc1           1        6             1                 1
    #  7   doc1           2        1             2                 0
    #  8   doc1           2        2             0                 1
    #  9   doc1           2        3             2                 0
    # 10   doc1           2        4             3                 2
    # 11   doc1           2        5             2                 0
    # 12   doc2           1        1             0                 0
    # 13   doc2           1        2             1                 1
    # 14   doc2           1        3             4                 2
    # 15   doc2           1        4             1                 1
    

    使用此数据:

    dat = read.table(text = "   doc_id sentence_id token_id head_token_id
    1    doc1           1        1             0
    2    doc1           1        2             1
    3    doc1           1        3             1
    4    doc1           1        4             3
    5    doc1           1        5             4
    6    doc1           1        6             1
    7    doc1           2        1             2
    8    doc1           2        2             0
    9    doc1           2        3             2
    10   doc1           2        4             3
    11   doc1           2        5             2
    12   doc2           1        1             0
    13   doc2           1        2             1
    14   doc2           1        3             4
    15   doc2           1        4             1", head = T)
    
        2
  •  1
  •   little girl    7 年前

    例如 "head_token_id" for doc_id == "doc_1" and sentence_id == 1 are 0, 1, 1, 3, 4, 1. 对于值3,只有两个唯一值较低(0和1)。所以我们想把3改为2。

    代码如下:

    levels<-function(parsedDataFrame)
    {parsedDataFrame$head_token_id=as.numeric(parsedDataFrame$head_token_id)
    for(doc in unique(parsedDataFrame[,1]))
        {for(prg in unique(parsedDataFrame[,2]))
            {for(stc in unique(parsedDataFrame[,3]))
                {
                    newDataFrame=parsedDataFrame[which(parsedDataFrame[,1]==doc & parsedDataFrame[,2]==prg & parsedDataFrame[,3]==stc),]
                    newDataFrame$sentenceLevel=sapply(newDataFrame$head_token_id,function(y) length(which(y>unique(newDataFrame$head_token_id))))
    
                    if(exists("levelsDF"))
                      levelsDF=rbind(levelsDF,newDataFrame)
                    else levelsDF=newDataFrame
                }
            }   
        }
        return(levelsDF)    
    }