【问题标题】:Coerce list from sapply to data frame produces columns of lists instead of int in R从 sapply 到数据框的强制列表生成列表列而不是 R 中的 int
【发布时间】:2017-11-20 03:27:13
【问题描述】:

我正在尝试强制/转换从sapply 返回的listdplyr::data_frame

data_df = tbl_df(data_frame(id=round(runif(10,1,5)),
                            Height=rnorm(10,65,10),
                            Weight=rnorm(10,100,25),
                            Strength=runif(10,1,10),
                            Age=rnorm(10,50,15)))

data2_df = tbl_df(data_frame(id=round(runif(40,1,5)),
                            Age=rnorm(40,50,15)))

FUN <- function(data_temp){
  BMI = data_temp$Weight / ((data_temp$Height^2) * 703)
  SBMI = BMI / data_temp$Strength
  id = data_temp$id
  data_older_friends = data2_df[data2_df$id == id & data2_df$Age > data_temp$Age,]
  nOFRIENDS = 0
  avgOFRIEND_AGE = NA
  if (nrow(data_older_friends)>0){
    nOFRIENDS = nrow(data_older_friends)
    avgOFRIEND_AGE = mean(data_older_friends$Age)
  }
  return_df=tbl_df(data_frame(id=id,BMI=BMI,SBMI=SBMI,nOFRIENDS=nOFRIENDS,avgOFRIEND_AGE=avgOFRIEND_AGE))
  return(return_df)
}

sapply_output = (sapply(1:nrow(data_df), function(x) FUN(data_df[x,])))

tbl_df(t(sapply_output))

输出是:

# A tibble: 5 x 5
         id       BMI      SBMI  nOFRIENDS avgOFRIEND_AGE
     <list>    <list>    <list>     <list>         <list>
1 <int [1]> <dbl [1]> <dbl [1]>  <int [1]>      <dbl [1]>
2 <int [1]> <dbl [1]> <dbl [1]>  <int [1]>      <dbl [1]>
3 <int [1]> <dbl [1]> <dbl [1]>  <int [1]>      <dbl [1]>
4 <int [1]> <dbl [1]> <dbl [1]>  <int [1]>      <dbl [1]>
5 <int [1]> <dbl [1]> <dbl [1]>  <int [1]>      <dbl [1]>

FUN(data_df) 的输出是(注意最后 2 列中的计算不准确):

# A tibble: 10 x 5
      id          BMI         SBMI nOFRIENDS avgOFRIEND_AGE
   <dbl>        <dbl>        <dbl>     <int>          <dbl>
 1     2 2.045586e-05 3.462166e-06         5       56.34759
 2     2 2.388499e-05 8.266183e-06         5       56.34759
 3     3 4.001101e-05 4.119298e-06         5       56.34759
 4     1 4.526758e-05 9.436741e-06         5       56.34759
 5     3 2.242063e-05 3.415824e-06         5       56.34759
 6     2 4.252556e-05 4.651436e-06         5       56.34759
 7     5 1.728240e-05 5.536207e-06         5       56.34759
 8     4 4.298384e-05 1.093979e-05         5       56.34759
 9     5 3.532514e-05 5.688031e-06         5       56.34759
10     3 2.001582e-05 2.673569e-06         5       56.34759

但是,我更喜欢包含 dbl 列的传统 data_frame,而不是包含 dbl 列表的列

我尝试过tibble::as_tibbleas.matrix 以及其他各种组合,但没有运气。另外,我不是在寻找join 解决方案,因为我的实际问题涉及 2 个非常大的表(这里我提出了问题的玩具版本)并且表 2 上的“分组”结果需要来自数据 1 中的行(因此按行解决方案似乎是有序的)

更新:%&gt;% unnest 可以解决问题

【问题讨论】:

  • 不要使用sapply——我认为只要FUN(data_df)就可以了。
  • 我需要使用sapply 的原因是我需要函数是逐行的。我已经更新了原始代码以反映这一点
  • R 使用矢量化操作 - data_temp$Weight / data_temp$Height 将每一行的 Weight 除以同一行中对应的 Height。无需显式循环。
  • FUN(data_df) 返回不准确的列计算 nFRIENDSavgFRIEND_AGE
  • 您实际上是在使用关系数据来解决更大的问题。这应该通过id 组对data2_df 的计算来解决,然后将其合并回data_df - 正如您所发现的那样,尝试一步完成所有操作会很麻烦。

标签: r dplyr sapply tibble


【解决方案1】:

我们可以使用map

library(dplyr)
library(purrr)
res <- map_df(seq_len(nrow(data_df)), ~FUN(data_df[.x,])) 
identical(res, tbl_df(t(sapply_output)) %>% 
                                       unnest)
#[1] TRUE

【讨论】:

  • @b_g 你可以使用map_df返回一个数据框,不需要bind_rows。我之前忘记了
  • 谢谢——对于那些阅读本文的人,%&gt;% unnest 似乎也能解决问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-30
  • 1970-01-01
  • 2021-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多