将函数应用于data.frame的每一行并保留列类

将函数应用于data.frame的每一行并保留列类,r,dataframe,apply,R,Dataframe,Apply,我想知道是否有办法将函数应用于data.frame的每一行,从而保留列类?让我们看一个例子来阐明我的意思: test <- data.frame(startdate = as.Date(c("2010-03-07", "2013-09-13", "2011-11-12")), enddate = as.Date(c("2010-03-23", "2013-12-01", "2012-01-05")), nEvent

我想知道是否有办法将函数应用于data.frame的每一行,从而保留列类?让我们看一个例子来阐明我的意思:

test <- data.frame(startdate = as.Date(c("2010-03-07", "2013-09-13", "2011-11-12")),
                   enddate = as.Date(c("2010-03-23", "2013-12-01", "2012-01-05")),
                   nEvents = c(123, 456, 789))
但是,这是不可能的,因为
apply
test
上调用
as.matrix
,从而将其转换为字符矩阵,并且所有列类都将丢失

我已经找到了两种解决方法,你们可以在下面找到,所以我的问题更多的是哲学性质的

library(magrittr)
############# Workaround 1
eventsPerDay2 <- function(startdate, enddate, nEvents) {
    n_days <- as.numeric(enddate - startdate) + 1
    data.frame(date = seq(startdate, enddate, by = "1 day"),
               nEvents = rmultinom(1, nEvents, rep(1/n_days, n_days)))
}

mapply(eventsPerDay2, test$startdate, test$enddate, test$nEvents, SIMPLIFY = F) %>%
    do.call(rbind, .)


############# Workaround 2
seq_along(test) %>%
    lapply(function(i) test[i, ]) %>%
    lapply(eventsPerDay1) %>%
    do.call(rbind, .)
库(magrittr)
#############解决方法1
事件每天2%
lappy(功能(i)测试[i,])%>%
lapply(eventsPerDay1)%>%
打电话(rbind,)
我的变通办法“问题”如下:

  • 解决方法1:这可能不是最好的理由,但我只是不喜欢
    mapply
    。它的签名与其他
    *apply
    函数不同(因为参数的顺序不同),我总是觉得
    for
    循环更清晰
  • 解决方法2:虽然非常灵活,但我认为第一眼就不清楚发生了什么

那么,是否有人知道一个函数的调用类似于
apply(test,1,eventsPerDay1)
,并且该函数可以工作?

我们可以使用
数据执行此操作。table

library(data.table)
res <- setDT(test)[,n_days := as.numeric(enddate - startdate) + 1 
           ][, .(date = seq(startdate, enddate, by= "1 day"),
          nEvents = c(rmultinom(1, nEvents, rep(1/n_days, n_days)))),
        by =  1:nrow(test)][, nrow := NULL]
str(res)
#Classes ‘data.table’ and 'data.frame':  152 obs. of  2 variables:
# $ date   : Date, format: "2010-03-07" "2010-03-08" "2010-03-09" "2010-03-10" ...
# $ nEvents: int  5 9 7 11 6 6 10 7 12 3 ...
库(data.table)
res另一个想法:

library(dplyr)
library(tidyr)

test %>%
  mutate(id = row_number()) %>%
  group_by(startdate) %>%
  complete(startdate = seq.Date(startdate, enddate, 1), nesting(id)) %>%
  group_by(id) %>%
  mutate(nEvents = rmultinom(1, first(nEvents), rep(1/n(), n()))) %>%
  select(startdate, nEvents)
其中:

#Source: local data frame [152 x 3]
#Groups: id [3]
#
#      id  startdate nEvents
#   <int>     <date>   <int>
#1      1 2010-03-07       6
#2      1 2010-03-08       6
#3      1 2010-03-09       6
#4      1 2010-03-10       7
#5      1 2010-03-11      12
#6      1 2010-03-12       5
#7      1 2010-03-13       8
#8      1 2010-03-14       5
#9      1 2010-03-15       5
#10     1 2010-03-16       9
## ... with 142 more rows
#来源:本地数据帧[152 x 3]
#组别:id[3]
#
#身份证起始日期
#           
#1      1 2010-03-07       6
#2      1 2010-03-08       6
#3      1 2010-03-09       6
#4      1 2010-03-10       7
#5      1 2010-03-11      12
#6      1 2010-03-12       5
#7      1 2010-03-13       8
#8      1 2010-03-14       5
#9      1 2010-03-15       5
#10     1 2010-03-16       9
## ... 还有142行

我也问过自己同样的问题

我要么最终将df拆分为一个列表(基本方式)


我同意他们应该是apply(xy,1,function(x))的一个基本实现,它不会强制转换为字符,但我想古人实现矩阵转换的高级原因我的原始思维无法理解。

如果你想保留这个类,使用
lappy
在行序列上循环,而不是
apply
@akrun感谢您的建议,但这不正是我在“解决方案2”中所做的吗?如果没有,请详细说明你的意思。谢谢是的,你说得对。我发布了一个使用
data.table
的解决方案。请检查这是否会使它变得更好工作环境1是最好的
apply()
用于处理矩阵(如果传入data.frame,它将通过
as.matrix
)转换),矩阵只能有一个原子数据表。不要将
apply()
data.frames
一起使用。
library(dplyr)
library(tidyr)

test %>%
  mutate(id = row_number()) %>%
  group_by(startdate) %>%
  complete(startdate = seq.Date(startdate, enddate, 1), nesting(id)) %>%
  group_by(id) %>%
  mutate(nEvents = rmultinom(1, first(nEvents), rep(1/n(), n()))) %>%
  select(startdate, nEvents)
#Source: local data frame [152 x 3]
#Groups: id [3]
#
#      id  startdate nEvents
#   <int>     <date>   <int>
#1      1 2010-03-07       6
#2      1 2010-03-08       6
#3      1 2010-03-09       6
#4      1 2010-03-10       7
#5      1 2010-03-11      12
#6      1 2010-03-12       5
#7      1 2010-03-13       8
#8      1 2010-03-14       5
#9      1 2010-03-15       5
#10     1 2010-03-16       9
## ... with 142 more rows
xy <- data.frame()
xy.list <- split(xy, 1:nrow(xy))
out <- lapply(xy.list, function(x) ...)
answer <- unlist(out)
xy %>%
rowwise() %>%
mutate(newcol = function(x) ....)