R 将非连续索引更改为连续索引
我有这样的数据:R 将非连续索引更改为连续索引,r,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
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
数据按“文档id”和“句子id”列分组。“head\u token\u id”列是订单列。但是,顺序值不是连续的。例如,doc\u id==“doc\u 1”
和句子\u id==1
的“head\u-token\u-id”的值是0、1、1、3、4、1
。我想将它们更改为连续值0、1、1、2、3、1
。我想在每组“文档id”和“句子id”中都这样做
我想要的输出是这样的,带有新的\u head\u token\u id列。
head_token_id中的数字0和1始终相同。但其余的数字可能相同,也可能不同。In取决于这个句子中是否有前面的数字。比如说
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句,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}
}
}
}
将变量视为一个因素,重新标记非常容易。然后我们可以强制它返回数值。我们使用的事实是,
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;重叠;rbind
等。这些方法的示例以及更多内容可以在R-FAQ上找到,您只需要使用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
我有答案。在一个文档和一句话中,我们必须找出有多少唯一值低于当前检查值,并替换此数字上的当前值。 例如,doc_id==“doc_1”和句子_id==1的
“head_token_id”的值为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)
}
levelsunique(新数据帧$head\u令牌\u id)))
如果(存在(“levelsDF”))
levelsDF=rbind(levelsDF,newDataFrame)
else levelsDF=newDataFrame
}
}
}
返回(levelsDF)
}
此操作的算法是什么?如果你只是想改变顺序,给DF传递一个行号向量来反映这一点。我试图找出这个算法,因为实际上我有一个非常大的数据集,包含100000个文档,我不明白的是,head\u token\u id
中的第七个数字是2?是的,head\u token\u id中的第七个数字是2。第七个数字是doc1第二句中的第一个单词。doc1,sentence2和doc2,sentence1在新的\u head\u token\u id列中是错误的。当我在我的计算机上使用您的代码时,只有doc1,sentence2是错误的。抱歉,没有意识到您还需要按句子分组。只需将其添加到groupby:groupby(dat,doc\u id,句子id)
,其余的都一样。答案编辑好了,还是不行。看doc1的句子2。。0和1应始终保持不变
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)
}