Как правило, когда кто-то хочет использовать sparklyr
для пользовательской функции ( т.е. ** непереведенных функций), они помещают их в spark_apply()
. Однако я встречал только примеры, когда один локальный фрейм данных либо copy_to()
, либо spark_read_csv()
для удаленного источника данных, а затем использовал spark_apply()
для него. Пример, только для иллюстративных целей:
library(sparklyr)
sc <- spark_connect(master = "local")
n_sim = 100
iris_samps <- iris %>% dplyr::filter(Species == "virginica") %>%
sapply(rep.int, times=n_sim) %>% cbind(replicate = rep(1:n_sim, each = 50)) %>%
data.frame() %>%
dplyr::group_by(replicate) %>%
dplyr::sample_n(50, replace = TRUE)
iris_samps_tbl <- copy_to(sc, iris_samps)
iris_samps_tbl %>%
spark_apply(function(x) {mean(x$Petal_Length)},
group_by = "replicate") %>%
ggplot(aes(x = result)) + geom_histogram(bins = 20) + ggtitle("Histogram of 100 Bootstrapped Means using sparklyr")
Похоже, что было бы возможно использовать это для любого диапазона непереведенных функций, поступающих из пакетов CRAN
или Bioconductor
, если только данные находятся в объекте Spark.
У меня возникла специфическая проблема c для .jpeg
изображений, когда я прочитал, что SparkR
может загрузить сжатое изображение (.jpeg
, .png
, et c. ) в необработанное представление изображения с помощью ImageIO
в Java библиотеке - вполне возможно, что sparklyr
также может сделать это.
RsimMosaic::composeMosaicFromImageRandom(inputImage, outputImage, pathToTilesLibrary)
функция принимает введите изображение и путь к плиткам, использованным для создания фотографии mosai c и выведите изображение ( пример здесь ).
Если эта функция сделала только одно изображение, и я знал, как превратить его в искровой объект, я мог бы представить, что команда будет выглядеть так: composeMosaicFromImageRandom(inputImage, outputImage, spark_obj)
. Тем не менее, эта функция берет путь к 30000 изображений.
Как можно создать 30 000 объектов Spark на пути к этим плиткам (.jpegs
) и затем использовать эту функцию?
Если базовый код действительно нужно изменить, я использовал jimhester/lookup
для предоставления исходного кода:
function (originalImageFileName, outputImageFileName, imagesToUseInMosaic,
useGradients = FALSE, removeTiles = TRUE, fracLibSizeThreshold = 0.7,
repFracSize = 0.25, verbose = TRUE)
{
if (verbose) {
cat(paste("\n ------------------------------------------------ \n"))
cat(paste(" R Simple Mosaic composer - random version \n"))
cat(paste(" ------------------------------------------------ \n\n"))
}
if (verbose) {
cat(paste(" Creating the library... \n"))
}
libForMosaicFull <- createLibraryIndexDataFrame(imagesToUseInMosaic,
saveLibraryIndex = F, useGradients = useGradients)
libForMosaic <- libForMosaicFull
filenameArray <- list.files(imagesToUseInMosaic, full.names = TRUE)
originalImage <- jpeg::readJPEG(filenameArray[1])
xTileSize <- dim(originalImage[, , 1])[1]
yTileSize <- dim(originalImage[, , 1])[2]
if (verbose) {
cat(paste(" -- Tiles in the Library : ", length(libForMosaic[,
1]), "\n"))
cat(paste(" -- Tile dimensions : ", xTileSize, " x ",
yTileSize, "\n"))
}
if (verbose) {
cat(paste("\n"))
cat(paste(" Reading the original image... \n"))
}
originalImage <- jpeg::readJPEG(originalImageFileName)
xOrigImgSize <- dim(originalImage[, , 1])[1]
yOrigImgSize <- dim(originalImage[, , 1])[2]
if (verbose) {
cat(paste(" -- Original image dimensions : ", xOrigImgSize,
" x ", yOrigImgSize, "\n"))
cat(paste(" -- Output image dimensions : ", ((xOrigImgSize -
2) * xTileSize), " x ", ((yOrigImgSize - 2) * yTileSize),
"\n"))
}
if (verbose) {
cat(paste("\n"))
cat(paste(" Computing the mosaic... \n"))
}
outputImage <- array(dim = c(((xOrigImgSize - 2) * xTileSize),
((yOrigImgSize - 2) * yTileSize), 3))
removedList <- c()
l <- 1
pCoord <- matrix(nrow = ((xOrigImgSize - 2) * (yOrigImgSize -
2)), ncol = 2)
for (i in 2:(xOrigImgSize - 1)) {
for (j in 2:(yOrigImgSize - 1)) {
pCoord[l, 1] <- i
pCoord[l, 2] <- j
l <- l + 1
}
}
npixels <- length(pCoord[, 1])
for (i in 1:npixels) {
idx <- round(runif(1, 1, length(pCoord[, 1])))
pixelRGBandNeigArray <- computeStatisticalQuantitiesPixel(pCoord[idx,
1], pCoord[idx, 2], originalImage, useGradients)
tileFilename <- getCloseMatch(pixelRGBandNeigArray,
libForMosaic)
startI <- (pCoord[idx, 1] - 2) * xTileSize + 1
startJ <- (pCoord[idx, 2] - 2) * yTileSize + 1
outputImage[startI:(startI + xTileSize - 1), startJ:(startJ +
yTileSize - 1), ] <- jpeg::readJPEG(tileFilename)
if (removeTiles) {
libForMosaic <- removeTile(tileFilename, libForMosaic)
removedList <- c(removedList, tileFilename)
if (length(libForMosaic[, 1]) < (fracLibSizeThreshold *
length(libForMosaicFull[, 1]))) {
idxs <- runif(round(0.25 * length(libForMosaicFull[,
1])), 1, length(removedList))
for (ii in 1:length(idxs)) {
libForMosaic <- addBackTile(removedList[idxs[ii]],
libForMosaic, libForMosaicFull)
}
removedList <- removedList[-idxs]
}
}
if (length(pCoord[, 1]) > 2) {
pCoord <- pCoord[-idx, ]
}
}
if (verbose) {
cat(paste("\n"))
cat(paste(" Done!\n\n"))
}
jpeg::writeJPEG(outputImage, outputImageFileName)
}
Обратите внимание: Моя первая попытка чтобы ускорить этот код, нужно было 1) использовать profvis
, чтобы найти узкие места ( т.е. для циклов for) 2) использовать пакет foreach
для циклов for. Это привело к более медленному коду, который предполагал, что я распараллеливался на слишком низком уровне. Как я понимаю, sparklyr
больше относится к распределению вычислений, чем к распараллеливанию, поэтому, возможно, это сработает.