更快的方式子集数据表,而不是for循环R

编程入门 行业动态 更新时间:2024-10-08 14:39:59
本文介绍了更快的方式子集数据表,而不是for循环R的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个数据表(您将需要安装的数据表包)在R中生成X和Y坐标和来自正态分布和均匀分布的随机数据值。坐标表示2000×1600阵列上的点,并且必须被分成16个较小的扇区,每个扇区500×400。这些扇区需要它们的正态分布值的平均值除以均匀分布值的min ^ 2。我还使用提供的函数startstop创建了两个变量x和y,它们具有16个扇区的坐标以及计算每个扇区的数字的函数。

I have a data table (you'll need the data table package installed) in R generated with X and Y coordinates and random data values from both normal and uniform distributions. The coordinates represent points on a 2000x1600 array and has to be divided into 16 smaller "sectors" each 500x400. These sectors need their mean of Normal Distribution values taken, divided by the min^2 of the Uniform Distribution values. I also created two variables x and y using a provided function startstop, that have the coordinates for the 16 sectors and a function that calculates the numbers for each sector.

library(data.table) DT <- data.table(X = rep(1:2000, times = 1600), Y = rep(1:1600, each = 2000), Norm =rnorm(1600*2000), Unif = runif(1600*2000)) sectorCalc <- function(x,y,DT) { sector <- numeric(length = 16) for (i in 1:length(sector)) { sect <- DT[X %between% c(x[[1]][i],x[[2]][i]) & Y %between% c(y[[1]][i],y[[2]][i])] sector[i] <- sCalc(sect) } return(sector) } startstop <- function(width, y = FALSE) { startend <- width - (width/4 - 1) start <- round(seq(0, startend, length.out = 4)) stop <- round(seq(width/4, width, length.out = 4)) if (length(c(start,stop)[anyDuplicated(c(start,stop))]) != 0) { dup <- anyDuplicated(c(start,stop)) stop[which(stop == c(start,stop)[dup])] <- stop[which(stop == c(start,stop)[dup])] - 1 } if (y == TRUE) { coord <- list(rep(start, each = 4), rep(stop, each = 4)) } else if (y == FALSE) { coord <- list(rep(start, times = 4), rep(stop, times = 4)) } return(coord) } x <- startstop(2000) y <- startstop(1600, T) sectorNos <- sectorCalc(x,y,DT)

startstop函数不是一个问题,但我需要一个更快的方法来子集数据表。必须对sectorCalc函数进行一些修改。 for循环是我能想到的最好的方法,但我没有太多的数据表经验。有关更快速地分解数据表的方法的任何想法?

The startstop function isn't really an issue but I need a faster way to subset the data table. Some modifications have to be made to the 'sectorCalc' function. The for loop was the best way I could think of but I don't have too much experience with data tables. Any ideas on a faster method of breaking up the data table?

推荐答案

不仅使用包 data.table ,而且还有 cut 函数来构建间隔groups:

A solution using not only the package data.table but also the cut function to build the interval "groups":

# Create your test data library(data.table) set.seed(123) # make random numbers reproducible to allow comparison of different answers DT <- data.table(X = rep(1:2000, times = 1600), Y = rep(1:1600, each = 2000), Norm =rnorm(1600*2000), Unif = runif(1600*2000)) # calculate the sector by cutting the x and y values into groups defined by the interval breaks DT[, x.sect := cut(DT[, X], c(0, 499, 1000, 1500, 2000), dig.lab=10)] # Intervals should be: seq(0, 2000, by=500) lower bound is less one since it is not included in the interval (see help for cut function) DT[, y.sect := cut(DT[, Y], c(0, 399, 800, 1200, 1600), dig.lab=10)] # Intervals should be: seq(0, 1600, by=400) # Now calculate per group (calculation logic "stolen" from the working answer of user "Symbolix" DT[, .(sect = mean(Norm)/min(Unif)^2), by=.(x.sect, y.sect)]

请注意:我认为第一和第二个间隔的大小在原始解决方案中是错误的(499,而不是500的x和399,而不是400的y,不能使用 seq 函数重现所需的间隔,但必须手动枚举间隔休息)。

Please note: I think the size of the first and second interval is wrong in the original solution (499 instead of 500 for x and 399 instead of 400 for y so that I could not use the seq function to reproduce your desired intervals but had to enumerate the interval breaks manually).

strong> Edit 1:我已经替换了添加x.sect和y.sect列的原始代码,改进的解决方案通过引用添加列(:= )。

Edit 1: I have replaced the original code that adds the x.sect and y.sect columns by an improved solution that adds columns by reference (:=).

编辑2:如果您想订购结果,您至少有两个选项:

Edit 2: If you want to order the result you have (at least) two options:

# "Chaining" (output is input of next) DT[, .(sect = mean(Norm)/min(Unif)^2), by=.(x.sect, y.sect)][order(x.sect, y.sect),] # Or: Use the "keyby" param instead of "by" DT[, .(sect = mean(Norm)/min(Unif)^2), keyby=.(x.sect, y.sect)]

编辑3 :新增了 dig.lab = 10 param至 cut 函数,以避免间隔断点的科学记数法。

Edit 3: Added dig.lab=10 param to cut function in code above to avoid scientific notation of the interval breaks.

更多推荐

更快的方式子集数据表,而不是for循环R

本文发布于:2023-11-29 15:47:03,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1646842.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:子集   更快   数据表   而不是   方式

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!