0

我正在使用 R 对 Wikidata 转储进行分析。我之前已经从 XML 转储中提取了我需要的变量,并在较小的 csv 文件中创建了我自己的数据集。这是我的文件的样子。

Q939818;35199259;2013-05-04T20:28:48Z;KLBot2;/* wbcreateclaim-create:2| */ [[Property:P373]], Tour de Pologne 2010
Q939818;72643278;2013-09-26T03:46:26Z;Coyau;/* wbcreateclaim-create:1| */[[Property:P107]]: [[Q1656682]]
Q939818;72643283;2013-09-26T03:46:28Z;Coyau;/* wbcreateclaim-create:1| */[[Property:P31]]: [[Q2215841]]
Q939818;90117273;2013-11-28T14:14:04Z;DanmicholoBot;/* wbsetlabel-add:1|nb */from the [no] label
Q939818;90117281;2013-11-28T14:14:07Z;DanmicholoBot;/* wbsetlabel-remove:1|no */
Q939818;92928394;2013-11-28T14:14:07Z;DanmicholoBot;/* wbsetlabel-remove:1|no */

不幸的是,提取变量的脚本有时会跳过一些标签,因此在某些行中,项目 ID(第一个值)不存在,它被“wikimedia page”替换。

我想通过检查第三列中的时间来推断缺少的项目 ID:如果缺少值的行中的时间在下一个之前,那么我可以假设项目 ID 是相同的(它们是两个相同值的修订版)。否则,项目 ID 将与上一行相同。

为此,我编写了一些代码,首先检查第一列中带有“wikimedia page”的所有行,然后执行我刚刚描述的操作:

wikimedia_lines <- grep("wikimedia page", wikiedits_clean$V1)

for (i in wikimedia_lines){
  if (wikiedits_clean$time[i] < wikiedits_clean$time[i + 1]) {
     wikiedits_clean$V1[i] <- wikiedits_clean$V1[i + 1] 
  }
  else {wikiedits_clean$V1[i] <- wikiedits_clean$V1[i - 1] }
}

但是,由于我的文件很大(约 650 万行),因此执行循环需要很长时间。是否有更多“R 风格”(如使用 apply 或 sapply)解决方案可以更有效地做到这一点?

谢谢你。

4

2 回答 2

0

我建议如下:

data <- read.table(filename,
                   sep=";",
                   header=TRUE,
                   colClasses=c("character","character","character","character","character"))

data$time <- as.POSIXct(data$time,format="%Y-%m-%dT%H:%M:%S")

m <- which( data$ID == "wikimedia page" )
n <- m[which( data$time[m]-data$time[m+1] >= 0 )]

cleanData <- data

cleanData$ID[n]             <- data$ID[n-1]
cleanData$ID[setdiff(m,n)]  <- data$ID[setdiff(m,n)+1]

“m”是缺少“ID”的行号向量。“n”是“m”中那些行号的向量,其中时间不早于下一行中的时间。

于 2015-08-04T12:48:59.957 回答
0

如果连续行中缺少 ID,我之前的解决方案无法填补所有空白。以下解决方案更复杂,但它可以处理这种情况:

data <- read.table(filename,
                   sep=";",
                   header=TRUE,
                   colClasses=c("character","character","character","character","character"))

data$time <- as.POSIXct(data$time,format="%Y-%m-%dT%H:%M:%S")

m <- sort( which( data$ID == "wikimedia page" ) )
d <- diff(c(-1,m))
e <- diff(c(0,diff(m)==1,0))

b1 <- c(-Inf, m[which( e>0 | (d>1 & e==0) )], Inf)
b2 <- c(-Inf, m[which( e<0 | (d>1 & e==0) )], Inf)

k1 <- b1[unlist(lapply( m, function(x){ which.max(x<b1)-1 }))]
k2 <- b2[unlist(lapply( m, function(x){ which.max(x<=b2)  }))]

n1 <- which(((data$time[k2+1]-data$time[m]<0) & k1>1) | k2==nrow(data) )
n2 <- setdiff(1:length(m),n1)

cleanData <- data

cleanData$ID[m[n1]] <- data$ID[k1[n1]-1]
cleanData$ID[m[n2]] <- data$ID[k2[n2]+1]

和以前一样,“m”是缺少 ID 的行号向量。向量“b1”和“b2”包含“m”中的那些行号,其中连续丢失ID的块分别开始和结束,即这些块的下限和上限。所以“m”是区间“b1[i]:b2[i]”的并集,其中“i”从 1 到“b1”和“b2”的长度。“k1”和“k2”也包含这些边界,但它们的长度与“m”相同,并且“m[j]”包含在每个索引“j”的块“k1[j]:k2[j]”中”。“m[j]”行中的 ID 设置为“k1[j]-1”行或“k2[j]+1”行中的 ID 之一。“m[j]”中时间的比较

于 2015-08-04T23:51:35.910 回答