Группа R по приблизительным значениям - PullRequest
0 голосов
/ 05 мая 2020

У меня есть фрейм данных R (250 000 строк), некоторые данные выглядят следующим образом:

df = data.frame(X = c(1000.005, 1000.7, 1200, 1566, 1766.55, 1767.30, 33.45, 33.25, 400.67, 400.77), Y = c(38.6, 38.4, 32.0, 32.01, 39.99, 39.20, 12.21, 12.11, 33.81, 33.91), Angle = c(50, 36, 27, 77, 26, 34, 29, 14, 37, 55)) 

Итак, моя цель - сгруппировать данные на основе приближения значений X и Y с разница не более 1. Для набора данных, показанного выше, расположение групп будет выглядеть следующим образом:

data.frame(X = c(1000.005, 1000.7, 1200, 1566, 1766.55, 1767.30, 33.45, 33.25, 400.67, 400.77), Y = c(38.6, 38.4, 32.0, 32.01, 39.99, 39.20, 12.21, 12.11, 33.81, 33.91), Angle = c(50, 36, 27, 77, 26, 34, 29, 14, 37, 55), group = c(1,1, 2, 3, 4,4, 5, 5, 6, 6))

Есть ли в R функция, которую я могу группировать по строкам, задавая их различия ( в моем случае разница будет 1)?

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Я думаю, что размер ваших данных все еще поддается вычислению с помощью группировки. Вот немного запутанный подход data.table.

library(data.table)
setDT(df)
group <- df[,ID := 1:.N][
  ,df[abs(X - .SD[,X]) < 1 & abs(Y - .SD[,Y]) < 1,.(ID2 = ID)],by = ID,.SDcols = c("X","Y")][
  ,.(df[ID,],df[ID2,])][
    ,Distance := sqrt((X-X.1)^2+(Y-Y.1)^2)][
      Distance <= 1,][
        !duplicated(ID.1),rleid(ID)]

df[,`:=`(Group = group, ID = NULL)]
df
#           X     Y Angle Group
# 1: 1000.005 38.60    50     1
# 2: 1000.700 38.40    36     1
# 3: 1200.000 32.00    27     2
# 4: 1566.000 32.01    77     3
# 5: 1766.550 39.99    26     4
# 6: 1767.300 39.20    34     5
# 7:   33.450 12.21    29     6
# 8:   33.250 12.11    14     6
# 9:  400.670 33.81    37     7
#10:  400.770 33.91    55     7

Сначала мы подмножество самого набора данных для строк, которые находятся в пределах 1 для X и Y. Точки не могут быть ближе 1, если они больше 1 в любом измерении. Мы используем .SDcols только для подмножества .SD столбцов, которые нас интересуют. Далее связываем ряды между собой. Затем мы вычисляем расстояние вручную по формуле евклидова расстояния. Затем мы выбираем строки, которые находятся в пределах 1. Строки упорядочены по ID из предыдущего шага, поэтому мы можем использовать rleid с !duplicated для создания групп. Затем просто добавьте это обратно к исходным данным, и все готово.

Вы узнаете, будет ли это работать, исходя из того, сколько времени и сколько памяти это занимает:

df[,ID := 1:.N][,df[abs(X - .SD[,X]) < 1 & abs(Y - .SD[,Y]) < 1,.(ID2 = ID)],by = ID,.SDcols = c("X","Y")]

Обратите внимание, что ожидаемый результат может содержать ошибку, поскольку расстояние между точками 5 и 6 равно 1.089:

dist(rbind(c(1766.550,39.99),c(1767.300,39.20)))
#         1
#2 1.089312
0 голосов
/ 05 мая 2020

Проблема немного сбивает с толку, даже с вашими комментариями, поэтому я поделюсь некоторыми возможными решениями.

Даже если вы уверены, что каждое наблюдение имеет соответствующее наблюдение, которое «ближе всего» к нему, как вы определяете расстояние? Стандартное евклидово расстояние? Но если у каждой пары действительно есть «дубликат», то почему бы просто не взглянуть на значения, которые имеют самое близкое, скажем, значение X, и если каким-то образом между двумя есть ie, то взглянуть на значения Y? Или наоборот? Если есть действительно уникальные пары наблюдений, любой подход должен дать один и тот же ответ. Так что просто выберите самый простой и создайте матрицу расстояний и выберите минимальное расстояние для каждого, и если для j-го наблюдения i-е наблюдение имеет минимальное расстояние, то вы знаете, что они образуют пару. Если вы хотите использовать оба (X, Y), просто используйте стандартное евклидово расстояние.

Далее следует вопрос о размере набора данных. 250,000 - это довольно много, поэтому использование dist, вероятно, не сработает. Честно говоря, учитывая вышеизложенное, я бы порекомендовал вам написать для l oop, где для i-го наблюдения, если j-е наблюдение является самым близким, вы формируете для них пару и обновляете набор данных, который вы ищете, до удалить их. Это не будет красиво, но должно работать довольно быстро. Сообщите нам, если у вас возникнут проблемы.

Наконец, как указано в комментариях, стандартный подход, вероятно, заключается в использовании некоторого подхода к кластеризации. Может быть, пусть размер кластера будет равен половине размера набора данных? Вы даже можете использовать поэтапный кластерный подход, при котором вы указываете половину размера набора данных на каждом шаге, просматриваете внутри групп, выбираете самые маленькие пары, а затем получаете обновленный набор данных, который вы снова группируете, и повторяйте, пока не получите уникальные пары .

При 250 000 строк оба этих подхода действительно не должны вызывать особых проблем.

...