2014-01-21 2 views
1

Я хочу уменьшить очень большой набор данных с двумя переменными в файл меньшего размера. То, что я хочу сделать, - это найти точки данных с одинаковыми значениями, а затем я хочу сохранить только начальные и конечные значения, а затем удалить все точки данных между ними. Например образец набора данных выглядит следующим образом:Уменьшите большой набор данных до меньшего набора данных, используя R

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 то есть так что я буду держать их, как это. Мне нужно написать условие i.e, если два или более точек данных имеют одинаковые значения, тогда сохраняются только начальные и конечные точки данных. Тогда следующие два значения также имеют одинаковое значение, то есть 0, и я сохраню эти два. Однако после этого есть 5 точек данных с одинаковыми значениями. Мне нужно написать такую ​​программу, чтобы я хотел написать только две точки данных i.e 363.708 & 363.875 и удалить точки данных между ними. После этого я буду хранить только две точки данных с нулевыми значениями i.e 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 

ответ

3

Если данные в dataframe 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 номерами строк.

+0

Автоматический +1 для использования 'rle' :-); ваш подход к передаче данных определенно превосходит мой kludge. –

+0

+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 
+0

+1 Большое спасибо за ваш ответ. –

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.

Смежные вопросы