R сравнивая неравные векторы с неравенством

У меня есть два одиночных векторных фрейма данных неравной длины

aa<-data.frame(c(2,12,35))
bb<-data.frame(c(1,2,3,4,5,6,7,15,22,36))

Для каждого наблюдения в aa я хочу посчитать количество экземпляров bb меньше чем aa

Мой результат:

   bb<aa 
1   1
2   7
3   9

Я смог сделать это двумя способами, создав функцию и применив apply, но мои наборы данных велики, и я позволил одному работать всю ночь без конца.

Что я имею:

fun1<-function(a,b){k<-colSums(b<a)
                    k<-k*.000058242}

system.time(replicate(5000,data.frame(apply(aa,1,fun1,b=bb))))
       user  system elapsed 
      3.813   0.011   3.883 

Во-вторых,

fun2<-function(a,b){k<-length(which(b<a))
                    k<-k*.000058242}

system.time(replicate(5000,data.frame(apply(aa,1,fun2,b=bb))))
   user  system elapsed 
  3.648   0.006   3.664 

Вторая функция немного быстрее во всех моих тестах, но я позволяю первой работать всю ночь на наборе данных, где bb>1.7m и aa>160k

Я нашел этот пост и пытался использовать with(), но не могу заставить его работать, также попытался цикл for без успеха.

Любая помощь или направление приветствуется.

Спасибо!

2 ответа

Решение
aa<-data.frame(c(2,12,35))
bb<-data.frame(c(1,2,3,4,5,6,7,15,22,36))
sapply(aa[[1]],function(x)sum(bb[[1]]<x))
# [1] 1 7 9

Несколько более реалистичных примеров:

n  <- 1.6e3
bb <- sample(1:n,1.7e6,replace=T)
aa <- 1:n
system.time(sapply(aa,function(x)sum(bb<x)))
#    user  system elapsed 
#   14.63    2.23   16.87 

n  <- 1.6e4
bb <- sample(1:n,1.7e6,replace=T)
aa <- 1:n
system.time(sapply(aa,function(x)sum(bb<x)))
#    user  system elapsed 
#  148.77   18.11  167.26 

Так с length(aa) = 1.6e4 это занимает около 2,5 мин (в моей системе), и процесс масштабируется как O(length(aa)) - нет ничего удивительного в этом. Поэтому, с вашим полным набором данных, он должен работать примерно через 25 минут. Все еще немного медленно. Может быть, кто-то еще придумает лучший способ.

Мой оригинальный пост, который я искал, сколько раз BB

Так что в моем примере

aa<-data.frame(c(2,12,35))
bb<-data.frame(c(1,2,3,4,5,6,7,15,22,36))

 x<-ecdf(bb[,1])

 x(2)

[1] 0.2

 x(12)

[1] 0.7

 x(35)

[1] 0.9

Чтобы получить ответы в моем исходном посте, мне нужно было бы умножить их на количество точек данных в пределах bb, в данном случае 10. Хотя первое не совпадает, потому что в моем исходном посте я указал bb

Я имею дело с большими наборами данных о высоте и высоте воды более 1 миллиона точек данных для каждой, но в конце я создаю кривую затопления. Я хочу знать, сколько земли будет затоплено при уровне воды с учетом вероятности превышения.

Таким образом, использование вышеупомянутой функции ecdf() для всех 1 миллиона точек данных по-прежнему будет занимать много времени, но я понял, что мне не нужны все точки данных для создания моей кривой.

Поэтому я применил функцию ecdf() ко всему набору земельных данных, но затем создал последовательность высот воды, достаточно большую, чтобы создать нужную мне кривую, но достаточно маленькую, чтобы ее можно было быстро вычислить.

land_elevation <- data.frame(rnorm(1e6))
water_elevation<- data.frame(rnorm(1e6))

cdf_land<- ecdf(land_elevation[,1])

elevation_seq <- seq(from = min(water_elevation[,1]), to = max(water_elevation[,1]), length.out = 1000)

land                  <- sapply(elevation_seq, cdf_land)

Мои результаты такие же, но они намного быстрее.

Другие вопросы по тегам