我有这样的数据:
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}
}
}
}
答案 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.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)
答案 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)
}