【问题标题】:Is there a way to get a function to return a data frame?有没有办法让函数返回数据框?
【发布时间】:2020-12-24 18:49:27
【问题描述】:

我正在尝试编写一个返回数据帧的函数。基本上,目标是拥有三列:一列列出某个标识符,一列报告该标识符在数据集 A 的一列中出现的频率,另一列报告该标识符在数据集 B 的一列中出现的频率。我写了这个功能并且无法弄清楚为什么它正在打印而不是存储为数据框。这特别令人费解,因为当我在函数外部运行“if”循环时,它会创建所需的数据框。任何帮助将不胜感激。

数据样本是:

UOF$identifier     Citations$identifier
1545               1712
1588               646
1640               1545
1545               1645
1545               646
1588               1545
                   1640
                   1640

我希望这个函数返回:

value    instances in dataset 1    instances in dataset 2
1545     3                         2
1588     2                         0
1640     1                         2
  join_analysis<-function(column_name_fromdataset1, column_name_fromdataset2){
  Dataset1<-as.numeric(column_name_fromdataset1)
  Dataset2<-as.numeric(column_name_fromdataset2)
  unique_values1<-unique(Dataset1)  
  count<-data.frame(matrix(NA,nrow=length(Dataset2),ncol=3))
  for (i in 1:length(unique_values1)){
    ID<-unique_values1[i]
    count[,3][i]<-sum(Dataset2==ID, na.rm = TRUE)
    count[,2][i]<-sum(Dataset1==ID, na.rm=TRUE)
    count[,1][i]<-unique_values1[i]
  }
  colnames(count)<-cbind("value","instances in dataset 1", "instances in dataset 2")
return(as.data.frame(count))
  }

【问题讨论】:

  • 如果您将列名作为字符串传递给函数,那么您需要在转换为数字之前根据列名对列进行子集化

标签: r dataframe counting


【解决方案1】:

我会建议这种dplyr 方法和一个内置函数来避免循环。该函数将两个参数作为字符串,它们属于每个数据集中的列名。之后,它会合并结果:

library(dplyr)
#Function
myfun <- function(x,y)
{
  #Dataset 1
  r1 <- df1 %>% group_by(id=df1[,x]) %>% summarise(N1=n())
  #Dataset 2
  r2 <- df2 %>% group_by(id=df2[,y]) %>% summarise(N2=n())
  #Join
  r3 <- left_join(r1,r2)
  #Fill
  r3 %>% replace(is.na(.),0) -> r3
  return(r3)
}
#Apply function
myfun(x = 'UOF',y = 'Identifier')

输出:

# A tibble: 3 x 3
     id    N1    N2
  <int> <int> <int>
1  1545     3     2
2  1588     2     0
3  1640     1     2

使用的一些数据:

#Data
df1 <- structure(list(UOF = c(1545L, 1588L, 1640L, 1545L, 1545L, 1588L
)), class = "data.frame", row.names = c(NA, -6L))
df2 <- structure(list(Identifier = c(1712L, 646L, 1545L, 1645L, 646L, 
1545L, 1640L, 1640L)), class = "data.frame", row.names = c(NA, 
-8L))

【讨论】:

    【解决方案2】:

    如果你想和base R一起,也许你可以试试merge + stack,如下所示

    merge(aggregate(. ~ ind, stack(table(UOF)), sum),
      aggregate(. ~ ind, stack(table(Citations)), sum),
      by = "ind", all.x = TRUE
    )
    

    给了

       ind values.x values.y
    1 1545        3        2
    2 1588        2       NA
    3 1640        1        2
    

    数据

    UOF <- data.frame(identifier = c(1545, 1588, 1640, 1545, 1545, 1588))
    Citations <- data.frame(identifier = c(1712, 646, 1545, 1645, 646, 1545, 1640, 1640))
    

    【讨论】:

      【解决方案3】:

      我们可以使用tablemerge 以更简单的方式做到这一点,而无需循环或使用任何外部包。我们只需要第一个数据集的unique 值来使“标识符”列成为factor,并从第一个数据集中分配levels,获取table 并执行merge(来自base R

      join_analysis <- function(dat1, dat2, colnm1) {
              lvls <- unique(dat1[[colnm1]])
              tbl1 <- table(factor(dat1[[colnm1]], levels = lvls))
              tbl2 <- table(factor(dat2[[colnm1]], levels = lvls))
              out <- merge(tbl1, tbl2, by = 'row.names')[-c(1, 4)]
              names(out) <- c('value', 'instances in dataset 1',  
                        'instances in dataset 2')
              return(out)
      
      }
      
      join_analysis(UOF, Citations, 'identifier')
      #   value instances in dataset 1 instances in dataset 2
      #1  1545                      3                      2
      #2  1588                      2                      0
      #3  1640                      1                      2
      

      或者另一个选项是pivot_wider

      library(dplyr)
      library(tidyr)
      bind_rows(UOF, Citations, .id = 'grp') %>% 
         filter(identifier %in% unique(UOF$identifier)) %>%
         count(grp, identifier) %>% 
         pivot_wider(names_from = grp, values_from = n, values_fill = 0)
      

      或者另一种选择是在list 的两个数据集中执行count,然后在reduceleft_join 中执行left_join

      library(purrr)
      list(UOF, Citations) %>%
         map(~ .x %>%
                count(identifier)) %>%
           reduce(left_join, by = 'identifier')
      

      数据

      UOF <- structure(list(identifier = c(1545, 1588, 1640, 1545, 1545, 1588
      )), class = "data.frame", row.names = c(NA, -6L))
      
      Citations <- structure(list(identifier = c(1712, 646, 1545, 1645, 646, 1545, 
      1640, 1640)), class = "data.frame", row.names = c(NA, -8L))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-23
        • 2021-05-22
        • 1970-01-01
        • 2019-11-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多