将非连续索引更改为连续

时间:2017-10-22 12:36:36

标签: r

我有这样的数据:

   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

数据按“doc_id”和“sentence_id”列分组。 “head_token_id”列是订单列。但是,订单值连续。例如,doc_id == "doc_1"sentence_id == 1的“head_token_id”值为0, 1, 1, 3, 4, 1。我想将它们更改为连续值0, 1, 1, 2, 3, 1。我想在“doc_id”和“sentence_id”的每一组中执行此操作。

我想要的输出与new_head_token_id列相似。 head_token_id中的数字0和1始终相同。但其余数字可能相同或不同。取决于该句中是否存在较早的数字。例如

   doc_id sentence_id token_id head_token_id new_head_token_id
4    doc1           1        4             3                 2

这里我们看到head_token_id中的3变为2,因为在head_token_id列中的这句话(句子1,文档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 个答案:

答案 0 :(得分:1)

这种重新贴标很容易将变量视为一个因素。然后我们可以将它强制转换为数字。我们使用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.tablebase::avebase::bysplit; 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)

答案 1 :(得分:1)

我已经回答了这个问题。在一个doc和一个句子中,我们必须找到多少个唯一值低于当前检查值并替换此数字的当前值。 例如,"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)    
}