将函数应用于data.frame的每一行并保留列类
我想知道是否有办法将函数应用于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
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) ....)