【问题标题】:how to pass the value for fun2 which is in fun1如何传递 fun1 中 fun2 的值
【发布时间】:2022-01-24 05:24:46
【问题描述】:

我尝试像在图像中那样将两列分开显示,但在 rbind(df, subrow) 中出现错误:结果的列数不是向量长度的倍数 (arg 2)

expand_collapse <- function(right_table){
  
  sector_list <- unique(right_table$Sector)
  df = data.frame("Sector1"=c(""),"Sector"=c(""),"Incubatee"=c(""),"Actual"=c(""))
  
  my_fun <- function(s){
    df1 = right_table[right_table$Sector==s,]
    sector1 = df1$Sector[1]
    Sector = df1$Sector[1]
    Incubatee = ""
    actual = as.character(nrow(df1))
    mainrow = c(sector1,Sector,Incubatee,actual) 
    df = rbind(df,mainrow)
    incubatee_list <<- unique(df1$Incubatee)
  }
  df = do.call(rbind,lapply(sector_list, my_fun))
  
  my_fun2 <- function(i){
    df2 = right_table[right_table$Incubatee==i,]
    sector1 = df1$Sector[1]
    Sector = ""
    Incubatee = df2$Incubatee[1]
    actual = nrow(df2)
    subrow = c(sector1,Sector,Incubatee,actual)
    df = rbind(df,subrow)
  }
  df = do.call(cbind,lapply(incubatee_list, my_fun2))
  df = df[2:nrow(df),]
  df$Actual = as.numeric(df$Actual)
  df_total = nrow(right_table)
  df = rbind(df,c("","Total","",df_total))
  return(df)
}

DT::datatable(expand_collapse(x), rownames = F,escape = FALSE,selection=list(mode="single",target="row"),options = list(pageLength = 50,scrollX = TRUE, dom = 'tp',ordering=F,columnDefs = list(list(visible=FALSE, targets=0),list(className = 'dt-left', targets = '_all'))),class='悬停单元格-边框条纹')

【问题讨论】:

    标签: r datatable


    【解决方案1】:

    我尝试过您的功能,但很难理解您到底想做什么。以下是我在代码中发现的一些不一致和问题:

    • 您在开头定义了sector_list,但在my_fun() 中使用&lt;&lt;- 定义了incubatee_list,目前尚不清楚原因。
    • my_fun()my_fun2() 似乎实际上没有返回任何内容,我不确定您是否打算在每个函数中的 df 变量上使用 &lt;&lt;-
    • my_fun2() 引用 df1 会导致错误。

    您可能不需要采用如此复杂的方法来生成屏幕截图中的表格。以下是您可以做的一个示例。

    # First I'm going to add one more row to the data so that I could demonstrate 
    # more clearly what will happen if there is more than one Incubatee per sector. 
    # I create "Test" under the sector "Energy and CleanTech" with a count of 5.
    library(tidyverse)
    x = x %>% 
      bind_rows(tibble(
        Incubatee = "Test", 
        Sector = "Energy & CleanTech",
        count = 5,
        type = "Actual",
        qtr = "Q2",
        year = 2021
      ))
    
    # A tibble: 3 x 12
      Incubatee     Sector   date        year month qtr   year_range count type  yrmo 
      <chr>         <chr>    <date>     <dbl> <fct> <chr> <chr>      <dbl> <chr> <fct>
    1 "SpotSense"   Health   2021-07-01  2021 Jul   Q2    2021-2022      1 Actu~ Jul-~
    2 "Devidayal S~ Energy ~ 2021-08-01  2021 Aug   Q2    2021-2022      1 Actu~ Aug-~
    3 "Test"        Energy ~ NA          2021 NA    Q2    NA             5 Actu~ NA   
    # ... with 2 more variables: qtr_yr <fct>, m_date <chr>
    

    这是使用 tidyverse 的建议管道。

    expand_collapse = function(data) {
      data %>% 
        split(.$Sector) %>% 
        map_df(function(sector_data) {
          main_row = tibble(
            Sector = sector_data$Sector[1],
            Incubatee = "",
            Actual = sum(sector_data$count)
          ) 
        
          incubatee_rows = sector_data %>% 
            group_by(Incubatee) %>% 
            summarise(
              Sector = "",
              Actual = sum(count)
            )
          
          bind_rows(main_row, incubatee_rows)
        }) %>% 
        # Create a total row
        bind_rows(tibble(
          Sector = "Total",
          Incubatee = "",
          Actual = sum(data$count)
        ))
    }
    

    演示输出:

    > expand_collapse(x)
    # A tibble: 6 x 3
      Sector               Incubatee                    Actual
      <chr>                <chr>                         <dbl>
    1 "Energy & CleanTech" ""                                6
    2 ""                   "Devidayal Solar Solutions "      1
    3 ""                   "Test"                            5
    4 "Health"             ""                                1
    5 ""                   "SpotSense"                       1
    6 "Total"              ""                                7
    

    编辑: 基本 R 解决方案,并注意我按行数定义 Actual,而不是使用 sum(count)

    create_sector_section = function(sector_data) {
      main_row = data.frame(
        Sector = sector_data$Sector[1],
        Incubatee = "",
        Actual = nrow(sector_data),
        stringsAsFactors = FALSE
      ) 
      
      incubatee_rows = lapply(
        unique(sector_data$Incubatee),
        function(inc) {
          data.frame(
            Sector = "",
            Incubatee = inc,
            Actual = sum(sector_data$Incubatee == inc),
            stringsAsFactors = FALSE
          )
        }
      )
      Reduce(rbind, x = c(list(main_row), incubatee_rows))
    }
    
    expand_collapse = function(data) {
      sector_data = split(data, data$Sector)
      sector_sections = lapply(sector_data, create_sector_section)
      total_row = data.frame(
        Sector = "Total",
        Incubatee = "",
        Actual = nrow(data),
        stringsAsFactors = FALSE
      )
      Reduce(rbind, x = c(sector_sections, list(total_row)))
    }
    

    输出

    > expand_collapse(x)
                  Sector                  Incubatee Actual
    1 Energy & CleanTech                                 2
    2                    Devidayal Solar Solutions       1
    3                                          Test      1
    4             Health                                 1
    5                                     SpotSense      1
    6              Total                                 3
    

    此解决方案对您的原始实现的主要改进:

    • 使用split() 获取每个不同扇区的数据帧列表。
    • 使用数据框创建所需输出的较小部分。
    • 使用 Reduce() 将所有内容重新组合在一起。

    【讨论】:

    • 我修改了示例代码@kybazzi 实际上我只需要将for循环转换为apply
    • 在我发布的版本中,我使用了类似的purrr::map_df()。您是否希望您的解决方案在基础 R 中?
    • base r 意味着它会更具可读性或者我不知道哪个有利于代码优化@kybazzi
    • 这取决于您的要求和偏好 - 从优化的角度来看,这两种解决方案都非常好。就可读性而言,这是主观的,但我认为我的实现更简单。如果您对给出的解决方案有任何具体问题,请告诉我,我会尽力解决。
    • 另外,请注意我偏离了您在问题中使用的逻辑,将Actual 定义为count 的总和,而不仅仅是行数。如果我对数据的理解不正确,您可能需要更改这些内容。
    猜你喜欢
    • 2016-12-23
    • 1970-01-01
    • 2021-08-31
    • 2020-01-06
    • 2020-09-30
    • 2013-09-05
    • 2014-02-21
    • 2019-06-23
    • 1970-01-01
    相关资源
    最近更新 更多