Как получить максимальные n расстояний путем наблюдения в большом кадре данных в R? - PullRequest
0 голосов
/ 31 марта 2020

Я работаю с набором данных Million Song и пытаюсь найти для каждой песни ближайшие 100 песен на евклидовом расстоянии для подмножества около 237 тыс. Песен. Код работает ниже, но оперативная память на моем ноутбуке позволяет мне разрезать только около 500 строк за раз, так что это будет МНОГО копирования и вставки. Будем очень благодарны за любые предложения.

tmp01 <- dist1 %>%
    slice(1:1000) %>%
    rename(track_id2 = track_id, artist_fam = artist_familiarity, 
        artist_hot = artist_hotttnesss, loud = loudness) %>%
    crossing(dist1) %>%
    mutate(dist_inv = 1 / ((artist_fam - artist_familiarity)^2 + 
            (artist_hot - artist_hotttnesss)^2 + (loud - loudness)^2)^.5) %>%
    filter(track_id != track_id2) %>%
    group_by(track_id2) %>%
    top_n(n = 100) %>%
    ungroup() %>%
    select(track_id2, track_id, dist_inv) %>%
    mutate(dist = 1 / dist_inv) %>%
    arrange(track_id2, dist)

1 Ответ

1 голос
/ 31 марта 2020

data.table больше подходит для объемных данных, чем dplyr. Операции будут быстрее и потребуют меньше оперативной памяти, если вы примените соответствующий глагол data.table, особенно оператор :=. Если вы не знакомы с data.table, я рекомендую вам виньетки пакета.

Решение об отказе от использования crossing̀ исходит из этой нити . Не уверен, что я правильно понял ключ слияния: я думаю, что вам нужны только комбинации track_id с одинаковыми значениями слева и справа (потому что вы делаете filter(track_id != track_id2) в своем коде), но дайте мне больше подробностей, если это не так , Чтобы выбрать топ n наблюдений с помощью data.table, вы должны использовать dist1[,head(.SD, 100),by = "track_id2"]

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

library(data.table)

setDT(dist1)

setnames(dist1,
   old = c("track_id", "artist_familiarity","artist_hotttnesss","loudness"),
   new = c("track_id2","artist_fam", "artist_hot", "loud"))

dist1[,as.list(dist1),by="track_id"]

dist1[, dist_inv1 :=  1 / ((artist_fam - artist_familiarity)^2 + 
            (artist_hot - artist_hotttnesss)^2 + (loud - loudness)^2)^.5]

dist_agg <- dist1[,head(.SD, 100),by = "track_id2"]
dist_agg <- dist_agg[,.SD,.SDcols = c("track_id2", "track_id", "dist_inv")]
dist_agg[,dist := 1/dist_inv]
dist_agg <- dist_agg[order(track_id2, dist)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...