我想将包含两个变量的非常大的数据集缩减为较小的文件。我想要做的是我需要找到具有相同值的数据点,然后我想只保留起始值和结束值,然后删除它们之间的所有数据点。例如 示例数据集如下所示:
363.54167 23.3699
363.58333 23.3699
363.625 0
363.66667 0
363.70833 126.16542
363.75 126.16542
363.79167 126.16542
363.83333 126.16542
363.875 126.16542
363.91667 0
363.95833 0
364 0
364.04167 0
364.08333 0
364.125 0
364.16667 0
364.20833 0
364.25 127.79872
364.29167 127.79872
364.33333 127.79872
364.375 127.79872
364.41667 127.79872
364.45833 127.79872
364.5 0
364.54167 0
364.58333 0
364.625 0
364.66667 0
364.70833 127.43202
364.75 135.44052
364.79167 135.25522
364.83333 135.12892
364.875 20.32986
364.91667 0
364.95833 0
这里,前两个点具有相同的值,即26.369
,所以我会保持原样。我需要写一个条件,即如果两个或多个数据点具有相同的值,则只保留起始和结束数据点。然后接下来的两个值也具有相同的值,即0
,我将保留这两个值。但是,之后有5个数据点具有相同的值。我需要编写一个程序,以便我只想写两个数据点,即363.708
& 363.875
并删除它们之间的数据点。之后,我将只保留两个值为零的数据点,即363.91667
和364.20833
。
我正在寻找的样本输出如下:
363.54167 23.3699
363.58333 23.3699
363.625 0
363.66667 0
363.70833 126.16542
363.875 126.16542
363.91667 0
364.20833 0
364.25 127.79872
364.45833 127.79872
364.5 0
364.66667 0
364.70833 127.43202
364.75 135.44052
364.79167 135.25522
364.83333 135.12892
364.875 20.32986
364.91667 0
364.95833 0
答案 0 :(得分:3)
如果您的数据位于列名DF
和a
的数据框b
中,则
runs <- rle(DF$b)
firsts <- cumsum(c(0,runs$length[-length(runs$length)]))+1
lasts <- cumsum(runs$length)
edges <- unique(sort(c(firsts, lasts)))
DF[edges,]
给出
> DF[edges,]
a b
1 363.5417 23.36990
2 363.5833 23.36990
3 363.6250 0.00000
4 363.6667 0.00000
5 363.7083 126.16542
9 363.8750 126.16542
10 363.9167 0.00000
17 364.2083 0.00000
18 364.2500 127.79872
23 364.4583 127.79872
24 364.5000 0.00000
28 364.6667 0.00000
29 364.7083 127.43202
30 364.7500 135.44052
31 364.7917 135.25522
32 364.8333 135.12892
33 364.8750 20.32986
34 364.9167 0.00000
35 364.9583 0.00000
rle
给出具有相同值的组的长度(如果您有更多的小数位,浮点精度可能会成为问题)。 firsts
和lasts
分别给出组的第一行和组的最后一行的行索引。将索引放在一起,对它们进行排序,并删除重复项(因为一组大小将列出与第一个和最后一行相同的行),然后按行号索引DF
。
答案 1 :(得分:1)
我在这里使用rle
(对于那些认识我的人来说并不奇怪:-)。请记住,您需要检查大致相等以避免浮点舍入问题,这是概念。 rle
将返回两个序列,其中一个序列告诉您重复一次值的次数,另一个告诉您值本身。由于您只想保留单值或双值,我们基本上“缩小”所有更长的序列值。
编辑:我认识到这是相对笨重的代码,与melt/cast
的温和联系应该更有效率。我只是喜欢这样做。
df<-cbind(1:20, sample(1:3,rep=T,20))
rdf<-rle(df[,2])
lenfoo<-rdf$lengths
cfoo<-cumsum(lenfoo)
repfoo<-ifelse(lenfoo==1,1,2)
outfoo<-matrix(nc=2)
for(j in 1:length(cfoo)) outfoo <- rbind( outfoo, matrix(rep(df[cfoo[j],],times=repfoo[j] ), nc=2,byrow=TRUE ) )
Rgames> df
[,1] [,2]
[1,] 1 2
[2,] 2 2
[3,] 3 3
[4,] 4 3
[5,] 5 3
[6,] 6 3
[7,] 7 3
[8,] 8 2
[9,] 9 2
[10,] 10 3
[11,] 11 1
[12,] 12 2
[13,] 13 2
[14,] 14 3
[15,] 15 1
[16,] 16 2
[17,] 17 1
[18,] 18 2
[19,] 19 3
[20,] 20 1
Rgames> outfoo
[,1] [,2]
[1,] NA NA
[2,] 2 2
[3,] 2 2
[4,] 7 3
[5,] 7 3
[6,] 9 2
[7,] 9 2
[8,] 10 3
[9,] 11 1
[10,] 13 2
[11,] 13 2
[12,] 14 3
[13,] 15 1
[14,] 16 2
[15,] 17 1
[16,] 18 2
[17,] 19 3
[18,] 20 1
答案 2 :(得分:0)
x = tapply(df[[1]], df[[2]], range)
给出值
cbind(unlist(x, use.names=FALSE), as.numeric(rep(names(x), each=2)))
得到一个矩阵。更明确地说,避免强制进出角色向量
u = unique(df[[2]])
rng = sapply(split(df[[1]], match(df[[2]], u)), range)
cbind(as.vector(rng), rep(u, each=2))
如果数据非常大,则按df [[1]]排序,找到df [[2]]的每个元素的第一个(最小值)和最后一个(最大值);结合这些
df = df[order(df[[1]]),]
res = rbind(df[!duplicated(df[[2]]),], df[!duplicated(df[[2]], fromLast=TRUE),])
res[order(res[[2]]),]
可能将子集的行名称设置为NULL。