2016-01-26 4 views
0

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

df 
    Var1 Var2 
    5 0 
    9 0 
    4 1 
    6 1 
    2 2 
    4 2 

затем он проходит через каждую строку и проверяет, что значение из других строк в кадре данных находятся ближе (в обоих Var1 и Переменная2) к значений Var1 и Var2 в строке, в которой вы находитесь. Затем вывод представляет собой список из тех строк, которые ближе всего к каждой другой строке. Например

myFunc(df) 

[[1]] 
[1] 3 4 

[[2]] 
integer(0) 

[[3]] 
[1] 1 6 

[[4]] 
[1] 1 

[[5]] 
integer(0) 

[[6]] 
[1] 3 

Так Ряд 1 является ближайшим к значениям в обеих строках 3 и 4, в то время как строка 2 не имеет никакой другой строки рядом с ним. Вот MyFunc

myFunc = function(t) { 
x=matrix(); x2=list() 
y = matrix(); y2 = list() 
for (i in 1:nrow(t)){ 
    for (j in 1:nrow(t)){ 
     #this will check for other rows <= 1 from the row I am currently in 
     if (abs(t[i,1] - t[j,1]) <= 1) { 
      x[j] = j 
     } else { x[j] = NA } 
     if (abs(t[i,2] - t[j,2]) <= 1) { 
      y[j] = j 
     } else { y[j] = NA } 
    } 
    x2[[i]] = x 
    y2[[i]] = y 
} 
for (i in 1:length(x2)){ 
    x2[[i]] = x2[[i]][!x2[[i]] == i] 
    y2[[i]] = y2[[i]][!y2[[i]] == i] 
} 
x2 = lapply(x2, function(x) x[!is.na(x)]) 
y2 = lapply(y2, function(x) x[!is.na(x)]) 

#this intersects Var1 and Var2 to find factors that are close to both Var1 and Var2 
z = list() 
for (i in 1:length(x2)){ 
    z[[i]] = intersect(unlist(x2[[i]]), unlist(y2[[i]])) 
} 
return(z)} 
+0

От ваш код, кажется, что-то вроде 'apply (as.matrix (dist (DF,« максимум »)) == 1L, 2, which)' может быть полезно? –

ответ

1

Предполагая, что вы работаете с двумя столбцами только и целыми числами в обоих, можно рассчитать фактическое расстояние между каждой точкой, используя dist с евклидово расстояние. Затем вы можете просто фильтровать эти расстояния больше 2^0,5.

Он будет работать, если вы работаете с целыми числами, потому что если расстояние в var1 или var2 равно 2 или более, вы хотите его отменить, но в любом из этих случаев оно всегда будет >= 2.

Если вы не работаете с целыми числами, вы все равно можете использовать dist, но каждый отдельный столбец обрабатывается отдельно и затем фильтрует их.

Я думаю, что-то вроде:

d1 <- dist(df$Var1) # or d1 <- dist(Var1) 
d2 <- dist(df$Var2) # or d2 <- dist(Var2) 

Теперь вы можете выбирать, какие из них менее 1

dF <- as.matrix(d1) <= 1 & as.matrix(d2) <= 1 
diag(dF) <- NA 

И, чтобы получить конечный результат вы можете

colnames(dF) <- NULL 
dF2 <- lapply(as.data.frame(dF), which) 
names(dF2) <- 1:nrow(df) 

# dF2 
# $`1` 
# [1] 3 4 

# $`2` 
# integer(0) 

# $`3` 
# [1] 1 6 

# $`4` 
# [1] 1 

# $`5` 
# integer(0) 

# $`6` 
# [1] 3 
+0

два столбца не всегда являются целыми числами – user3067923

+0

, поэтому я попробовал функцию dist, которую вы предложили, но она работает только иногда. Я в основном получаю это (пример), где должно было быть сообщено TRUE, но вместо этого я получаю FALSE. Var1 Значение Var2 1 4 FALSE 1 5 FALSE – user3067923

+0

может привести пример, когда код не работает? Я попытался использовать структуру (список (Var1 = c (1, 1), Var2 = c (4, 5)), .Names = c ("Var1", "Var2"), row.names = c (NA, -2L), class = "data.frame") 'и он работает хорошо. Используйте 'dput' для экспорта переменной в текстовом формате. –

0

Ммм ... У Вас есть O (N 2 ) алгоритм. Что делать это так:

  • Добавить индекс/ID столбца df$ID <- seq.int(nrow(df)) (O (N))
  • Сортировать df по Var1, используя стабильную сортировку (O (N журнал (N)))
  • Один линейный переходить столбец делать различия, построение логического вектора (O (N))
  • Получить индексы от ID колонке (O (N))

же для Var2

, то вы можете сделать ваше пересечение результатов