Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 有效地计算一个数据帧与另一个数据帧的比例_R_Performance_Dataframe_Dplyr - Fatal编程技术网

R 有效地计算一个数据帧与另一个数据帧的比例

R 有效地计算一个数据帧与另一个数据帧的比例,r,performance,dataframe,dplyr,R,Performance,Dataframe,Dplyr,我有这个数据框: set.seed(1) df <- cbind(matrix(rnorm(26,100),26,100),data.frame(id=LETTERS,parent.id=sample(letters[1:5],26,replace = T),stringsAsFactors = F)) 但是对于我的数据的真实维度:length(df$id)=10000,有1024个测量值,这还不够快 如果理想情况下使用dplyr函数,您知道如何改进这一点吗?您的数据存在的问题是所有行都

我有这个
数据框

set.seed(1)
df <- cbind(matrix(rnorm(26,100),26,100),data.frame(id=LETTERS,parent.id=sample(letters[1:5],26,replace = T),stringsAsFactors = F))
但是对于我的数据的真实维度:
length(df$id)
=10000,有1024个测量值,这还不够快


如果理想情况下使用
dplyr
函数,您知道如何改进这一点吗?

您的数据存在的问题是所有行都是相互重复的,因此我稍微更改了它以反映数据集中的不同值

数据:

set.seed(1L)
df <- cbind(matrix(rnorm(2600), nrow = 26, ncol = 100),data.frame(id=LETTERS,parent.id=sample(letters[1:5],26,replace = T),stringsAsFactors = F))
library('data.table')
setDT(df)  # assign data.table class by reference

# compute sum for each `parent.id` for each column (100 columns)
sum_df <- df[, .SD, .SDcols = which(colnames(df) != 'id' )][, lapply(.SD, sum ), by = .(parent.id ) ] 

# get column names for sum_df and df which are sorted for consistency
no_pid_id_df  <- gtools::mixedsort( colnames(df)[ ! ( colnames(df) %in% c( 'id', 'parent.id' ) ) ] )
no_pid_sum_df <-  gtools::mixedsort( colnames(sum_df)[ colnames(sum_df) != 'parent.id' ] )

# match the `parent.id` for each `id` and then divide its value by the value of `sum_df`.
df[, .( props = { 
  pid <- parent.id
  unlist( .SD[, .SD, .SDcols = no_pid_id_df ] ) /
    unlist( sum_df[ parent.id == pid, ][, .SD, .SDcols = no_pid_sum_df ] )
  }, parent.id ), by = .(id)]
#       id       props parent.id
#    1:  A -0.95157186         e
#    2:  A  0.06105359         e
#    3:  A -0.42267771         e
#    4:  A -0.03376174         e
#    5:  A -0.16639600         e
# ---                         
# 2596:  Z  2.34696158         e
# 2597:  Z  0.23762369         e
# 2598:  Z  0.60068440         e
# 2599:  Z  0.14192337         e
# 2600:  Z  0.01292592         e
library('microbenchmark')
microbenchmark( sathish(), frank(), dan())
# Unit: milliseconds
#     expr         min         lq       mean    median         uq       max neval cld
# sathish() 404.450219 413.456675 433.656279 420.46044 429.876085 593.44202   100   c
# frank()     2.035302   2.304547   2.707019   2.47257   2.622025  18.31409   100   a  
# dan()      17.396981  18.230982  19.316653  18.59737  19.700394  27.13146   100   b 
基准测试:

set.seed(1L)
df <- cbind(matrix(rnorm(2600), nrow = 26, ncol = 100),data.frame(id=LETTERS,parent.id=sample(letters[1:5],26,replace = T),stringsAsFactors = F))
library('data.table')
setDT(df)  # assign data.table class by reference

# compute sum for each `parent.id` for each column (100 columns)
sum_df <- df[, .SD, .SDcols = which(colnames(df) != 'id' )][, lapply(.SD, sum ), by = .(parent.id ) ] 

# get column names for sum_df and df which are sorted for consistency
no_pid_id_df  <- gtools::mixedsort( colnames(df)[ ! ( colnames(df) %in% c( 'id', 'parent.id' ) ) ] )
no_pid_sum_df <-  gtools::mixedsort( colnames(sum_df)[ colnames(sum_df) != 'parent.id' ] )

# match the `parent.id` for each `id` and then divide its value by the value of `sum_df`.
df[, .( props = { 
  pid <- parent.id
  unlist( .SD[, .SD, .SDcols = no_pid_id_df ] ) /
    unlist( sum_df[ parent.id == pid, ][, .SD, .SDcols = no_pid_sum_df ] )
  }, parent.id ), by = .(id)]
#       id       props parent.id
#    1:  A -0.95157186         e
#    2:  A  0.06105359         e
#    3:  A -0.42267771         e
#    4:  A -0.03376174         e
#    5:  A -0.16639600         e
# ---                         
# 2596:  Z  2.34696158         e
# 2597:  Z  0.23762369         e
# 2598:  Z  0.60068440         e
# 2599:  Z  0.14192337         e
# 2600:  Z  0.01292592         e
library('microbenchmark')
microbenchmark( sathish(), frank(), dan())
# Unit: milliseconds
#     expr         min         lq       mean    median         uq       max neval cld
# sathish() 404.450219 413.456675 433.656279 420.46044 429.876085 593.44202   100   c
# frank()     2.035302   2.304547   2.707019   2.47257   2.622025  18.31409   100   a  
# dan()      17.396981  18.230982  19.316653  18.59737  19.700394  27.13146   100   b 

让我们将这些选项与
microbenchmark
进行比较,所有选项都使用@Sathish答案中数据集的新定义:

OP方法:

Units: seconds
      min      lq     mean   median       uq      max neval
 1.423583 1.48449 1.602001 1.581978 1.670041 2.275105   100
@Sathish方法将其速度提高约5倍。当然,这是很有价值的

Units: milliseconds
      min      lq     mean   median       uq      max neval
 299.3581 334.787 388.5283 363.0363 398.6714 951.4654   100 
下面一个可能的base R实现使用了高效R代码的原理,将性能提高了约65倍(24毫秒,而不是1582毫秒):

下面是基本的R实现。与OP的实现一样,
parent.id
id
列不包括在结果结构中(此处为
分数
)<代码>分数是一个矩阵,其行按照排序(交互(df$id,df$parent.id,drop=TRUE))排序


values“我正在寻找一种快速的方法来获取它的
parent.id
的测量值中每个
df$id
(每100个测量值)的分数。”我不理解这句话。你能提供一个例子来详细说明你想要计算什么吗?编辑我的帖子以使其更清晰。你的数据框的尺寸是多少?10000 x 1024-参见编辑的帖子如果你关心速度,转换为长格式可能会有所帮助。对于看起来像
res=melt(DT,id=c(“id”,“parent.id”))[,v:=value/sum(value),by=(variable,parent.id)][]
的data.table,返回到wide,
dcast(res,id+parent.id~ variable,value.var=“v”)
这不是特别快。与OPs相比,这是一个因数5的改进。向上投票:)我不知道我是否认为它会更快。如果你想加快速度,你可以转换成一个矩阵,在这种情况下,行与列或宽与长是不相关的。你是如何实现Frank的方法的?很好!如果你想比较的话,请随意添加我的。