将列和数据框参数传递给lapply()中的函数?

时间:2019-10-24 05:35:46

标签: r dplyr apply lapply

我有一个函数,它接受一个数据框和该数据框中的一列。我想使用lapply()将函数应用于数据帧中的每一列,但是我不确定该怎么做。 我认为它应该类似于:

#dataframe is called kstarter
my_func(df, col) {
 ...
}
lapply(kstarter, arg1=kstarter, arg2=??)

但是我似乎无法正常工作。 arg2如何引用lapply遍历的每一列?我感谢您的帮助!

编辑:

我要应用的功能是:

get_col_info <- function(col, df) {
  unique_vals <- df %>% 
    select(col) %>%
    distinct() 
  num_u_vals <- nrow(unique_vals)
  if (is.numeric(df[[col]])) {
    return(list(
      min = min(df[[col]]),
      max = max(df[[col]]),
      mean = mean(df[[col]])
    ))
  } else if ((!is.numeric(df[[col]])) & num_u_vals < 10) {
    return(list(
      n_values = num_u_vals,
      unique_values = unique_vals %>% pull()
    ))
  } else if (!is.numeric(df[[col]]) & num_u_vals >= 10) {
    return(list(
      n_values = num_u_vals,
      sample_values = sample(df[[col]], size=10)
    ))
  }
}

get_col_info需要将列名和数据框作为参数。 我想创建一个列表,使用lapply获取数据帧中每一列的col信息,类似list <- lapply(kstarter, get_col_info(current_col, kstarter)),但我不知道语法。请帮忙!

2 个答案:

答案 0 :(得分:1)

在数据框上使用lapply时,它会自动在列上循环。这是一个使用iris数据集的示例,但是如果您提供一些可重复的示例,我可以将其调整为适合您的数据。

lapply(iris, mean)

您可以像这样使用您自己的自定义匿名函数来代替函数mean

lapply(iris, function(column){
  rtn=mean(column, na.rm=T)
  return(rtn)
})

或者您的内置函数如下:

my_func = function(column){
  rtn=mean(column, na.rm=T)
  return(rtn)
}
lapply(kstarter, myfunc)

此外,我建议您从map包中查找purrr函数,因为它可以更好地控制返回类型。例如purrr::map(kstarter, myfunc)将返回list,而purrr::map_df(kstarter, myfunc)将返回data.frame

答案 1 :(得分:0)

问题始于如何定义函数。您的函数应将列(或向量)作为变量。这是@DanChaltiel发布的内容的一小部分。您可以这样:

library(tidyverse)

df = data.frame(
 A=sample(1:10,20,replace=T),
 B=sample(1:10,20,replace=T),
 C=sample(letters,20,replace=T),
 D=rep(letters[1:4],5)
)
# slightly modified your function
# but you can clean it up more
# a lot of redundancy 
get_col_info <- function(col) {
  num_u_vals <- n_distinct(col)
  if (is.numeric(col)) {
    return(list(
      min = min(col),
      max = max(col),
      mean = mean(col)
    ))
  } else if ((!is.numeric(col)) & num_u_vals < 10) {
    return(list(
      n_values = num_u_vals,
      unique_values = unique(col)
    ))
  } else if (!is.numeric(col) & num_u_vals >= 10) {
    return(list(
      n_values = num_u_vals,
      sample_values = sample(col, size=10)
    ))
  }
}
## as Dan Chaltiel suggested
lapply(df,get_col_info)
## or purrr
df %>% map(get_col_info)