R:类似于apply的函数返回数据框吗?

时间:2016-05-02 12:42:56

标签: r dataframe

我想将函数应用于数据框的每一行。使用apply,结果本身不再是数据框,它看起来更像是列表或矩阵? (我不知道足够的R能够从输出中得知,只是它不是数据帧)

用于将函数应用于数据帧的每一行,返回新数据帧的正确函数是什么?

我想要应用于每一行的功能:

map_uri <- function(request){
    ret <- request
    uri_stem <- uri_map[uri_map[,1] == request["cs-uri-query"],2]
    if(length(uri_stem) > 0){
        ret <- request
        ret["cs-uri-stem"] <- uri_stem
        ret["cs-uri-query"] <- "-"
    }
    if(request["cs-uri-stem"] == "/index.html"){
        ret["cs-uri-stem"] = "/"
    }

    return(ret)

}

我在尝试什么:

cleansed <- apply(requests, 1, map_uri)
cleansed[,c("cs-uri-query", "cs-uri-stem")]

给了我错误

  

Fehler in cleansed [,c(“cs-uri-stem”,“cs-uri-query”)]:Indizierung   außerhalbderGrenzen

(索引越界)

由于某种原因,结构的变化使得上面的索引错误。

[编辑]

数据使这成为一个有效的例子:

uri_map.tsv http://pastebin.com/XhUuTMqA

uri_map <- read.table("http://pastebin.com/raw/XhUuTMqA", sep="\t", header=FALSE)

输入转换函数的数据:

http://pastebin.com/b7ja4rKn

requests&lt; - read.table(“http://pastebin.com/raw/b7ja4rKn”,sep =“”,header = TRUE)

2 个答案:

答案 0 :(得分:15)

可以使用申请系列,但是,你是对的,结果是matrixdata.frame。回到data.frame

并不是什么大不了的事

你的函数需要在列之间返回一致的内容(原始iris而不是iris[, 1:4]在下面不起作用,因为iris$Species这是一个3级因子{{1} }从数字列返回6个数字),这是reproducible有用的地方。下面,我使用了summaryiris

  1. 申请summary
  2. sapply as.data.frame(apply(iris[, 1:4], 2, summary))
  3. lapply as.data.frame(sapply(iris[, 1:4], summary))

答案 1 :(得分:0)

我刚刚实现了这个函数,它将 FUN 作为列表应用于行并将结果连接到 tibble

library(magrittr)

lapply_rows <- function(df, return_tibble = TRUE, FUN, ...) {
  df_rownames <- rownames(df)

  res <- lapply(purrr::transpose(df), FUN = FUN, ...) %>%
    purrr::map_depth(2, function(x) {
      if (length(x) != 1) {
        return(list(x))
      } else {
        return(x)
      }
    }) %>%
    dplyr::bind_rows()

  if (!return_tibble) {
    res <- as.data.frame(res)
    rownames(res) <- df_rownames
  }

  return(res)
}

dfpurrr::transpose(df) 转换为列表列表,其中每个子列表是原始 df 的一行。 FUN 必须返回一个命名列表,它也可以包含长度不为 1 的元素。然后将这些元素包装在 list() 中(类似 data.frame 的对象的列类型也可以是列表)。如果 return_tibbleFALSE,则结果被强制为 data.frame 并设置原始行名。

示例:

df <- lapply_rows(mtcars, FUN = function(row_list) {
  row_list$cyl_2 <- row_list$cyl ** 2
  row_list$colors <- c("red", "green", "blue")
  row_list$sublist <- mtcars[1:5, 1:5]
  return(row_list)
})

head(df)
# A tibble: 6 x 14
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb cyl_2 colors    sublist         
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <list>    <list>          
1  21       6   160   110  3.9   2.62  16.5     0     1     4     4    36 <chr [3]> <df[,5] [5 × 5]>
2  21       6   160   110  3.9   2.88  17.0     0     1     4     4    36 <chr [3]> <df[,5] [5 × 5]>
3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1    16 <chr [3]> <df[,5] [5 × 5]>
4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1    36 <chr [3]> <df[,5] [5 × 5]>
5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2    64 <chr [3]> <df[,5] [5 × 5]>
6  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1    36 <chr [3]> <df[,5] [5 × 5]>

返回 data.frame 的示例:

df2 <- lapply_rows(mtcars, return_tibble = FALSE, FUN = function(row_list) {
  row_list$cyl_2 <- row_list$cyl ** 2
  row_list$colors <- c("red", "green", "blue")
  row_list$sublist <- mtcars[1:5, 1:5]
  return(row_list)
})

head(df2)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb cyl_2           colors
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4    36 red, green, blue
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4    36 red, green, blue
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1    16 red, green, blue
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1    36 red, green, blue
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2    64 red, green, blue
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1    36 red, green, blue
                                                                                                                                                                                       sublist
Mazda RX4         21.00, 21.00, 22.80, 21.40, 18.70, 6.00, 6.00, 4.00, 6.00, 8.00, 160.00, 160.00, 108.00, 258.00, 360.00, 110.00, 110.00, 93.00, 110.00, 175.00, 3.90, 3.90, 3.85, 3.08, 3.15
Mazda RX4 Wag     21.00, 21.00, 22.80, 21.40, 18.70, 6.00, 6.00, 4.00, 6.00, 8.00, 160.00, 160.00, 108.00, 258.00, 360.00, 110.00, 110.00, 93.00, 110.00, 175.00, 3.90, 3.90, 3.85, 3.08, 3.15
Datsun 710        21.00, 21.00, 22.80, 21.40, 18.70, 6.00, 6.00, 4.00, 6.00, 8.00, 160.00, 160.00, 108.00, 258.00, 360.00, 110.00, 110.00, 93.00, 110.00, 175.00, 3.90, 3.90, 3.85, 3.08, 3.15
Hornet 4 Drive    21.00, 21.00, 22.80, 21.40, 18.70, 6.00, 6.00, 4.00, 6.00, 8.00, 160.00, 160.00, 108.00, 258.00, 360.00, 110.00, 110.00, 93.00, 110.00, 175.00, 3.90, 3.90, 3.85, 3.08, 3.15
Hornet Sportabout 21.00, 21.00, 22.80, 21.40, 18.70, 6.00, 6.00, 4.00, 6.00, 8.00, 160.00, 160.00, 108.00, 258.00, 360.00, 110.00, 110.00, 93.00, 110.00, 175.00, 3.90, 3.90, 3.85, 3.08, 3.15
Valiant           21.00, 21.00, 22.80, 21.40, 18.70, 6.00, 6.00, 4.00, 6.00, 8.00, 160.00, 160.00, 108.00, 258.00, 360.00, 110.00, 110.00, 93.00, 110.00, 175.00, 3.90, 3.90, 3.85, 3.08, 3.15

(您可以看到 tibble 更好地处理了 <list> 列)