类似apply的函数,返回一个 Dataframe ?

ifsvaxew  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(113)

我想对数据框的每一行应用一个函数。使用apply,结果本身就不是一个数据框了,它看起来更像一个列表或矩阵?(我不知道足够的R来判断我得到的输出,只是它不是一个数据框)
哪一个是正确的函数,用于将函数应用于 Dataframe 的每一行,返回一个新的 Dataframe ?
我想应用于每一行的函数:

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ßerhalb der Grenzen
(索引越界)
由于某种原因,结构的变化使上述索引错误。
[编辑]
数据使这成为一个工作示例:
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 <- read.table(“http://pastebin.com/raw/b7ja4rKn“,sep=”“,header=TRUE)

4xy9mtcn

4xy9mtcn1#

你可以使用apply family,但是,你是对的,结果要么是matrix,要么是list。不过回到data.frame也没什么大不了的。
你的函数需要在列之间返回一致的东西(raw iris而不是iris[, 1:4]在下面不起作用,因为iris$Species是一个有3个级别的因子,其中summary从数值列返回6个数值),这就是可重现的地方。下面,我使用了irissummary
1.申请as.data.frame(apply(iris[, 1:4], 2, summary))
1.sapplyas.data.frame(sapply(iris[, 1:4], summary))
1.lapplydo.call(cbind, lapply(iris[, 1:4], summary))

yacmzcpb

yacmzcpb2#

我刚刚实现了这个函数,它将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的元素。这些元素然后被 Package 在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

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

kzipqqlq

kzipqqlq3#

使用dapr 1.0+,你可以在每行rowwise()上应用一个函数:

df <- tibble(x = 1:6, y = 2:7, z = 3:8)
# Compute the mean of x, y, z in each row
df %>% rowwise() %>% mutate(m = mean(c(x, y, z)))

字符串
如果你的函数已经被向量化了(就像这个例子中的+),你不需要rowwise()

df %>% mutate(s = x + y + z)


如果函数返回多个值,summarize()可以将这些值解压缩到单独的列中。

相关问题