![](/img/trans.png)
[英]What is the tidyverse way to apply a function designed to take data.frames as input across a grouped tibble in R?
[英]Apply function to data frames grouped by
我想將一個函數應用於數據幀的子集,這些子集是在按變量分組后從初始幀開始的。 因此,我正在尋找與apply
或類似方法等效的包裝器, apply
整個數據幀作為輸入並輸出矢量。 這是因為手邊的函數需要來自不同位置的行和列的條目,並且不能簡化為僅使用行和列,因此具有lapply
或apply(df, 1(2),...)
讓我們考慮以下示例:
iris <- data.table(iris)
my.function <- function(sub.data){
v <- c(NA)
for(j in 2:dim(sub.data)[1]){
if(sub.data[j,1, with = FALSE] > sub.data[j-1,2, with = FALSE]+2){
v[j] <- "ok"
} else {
v[j] <- "not ok"
}
}
return(v)
}
執行my.function(iris)
可以正常工作,但是假設我只想將功能應用於具有相同Species的組。 因此,在data.table
語法中,它應類似於:
results <- iris[,
wrapper(.SD, my.function),
by = Species
]
wrapper
是我正在尋找的環境,類型為lapply
或類似類型。 同樣,也可以使用dplyr
包,但我不知道相應的語法是什么:我已經嘗試過
results <- iris %>%
group_by(Species) %>%
summarise(results = my.function(iris))
但這似乎無法產生正確的結果,因為它仍然針對每個物種的整個數據集運行,而不是分成子集。
看來您這里不需要wrapper
。 只需在.SD上運行您的功能即可滿足您的需求。
library(data.table)
#your function works with a data.table
#by below will create smaller data tables on which you can directly
#run my.function on
iris[, my.function(.SD), by=Species]
輸出:
Species V1
1: setosa NA
2: setosa not ok
3: setosa not ok
4: setosa not ok
5: setosa not ok
---
146: virginica ok
147: virginica ok
148: virginica ok
149: virginica ok
150: virginica ok
目的是不使用軟件包嗎?
輸出向量的長度是否與data.frame的行數相同? 如果是這樣,請在我們使用測試my.function
地方嘗試ave
,該my.function
返回行數乘以其輸入數據幀的列數:
my.function <- function(x) prod(dim(x)) # test function
ave(1:nrow(iris), iris$Species, FUN = function(ix) my.function(iris[ix, ]))
## [1] 250 250 250 250 250 250 250 250 ...
如果my.function返回的向量的長度與輸入的行數相同,則上述方法也適用。
在這種情況下,如果只需要長度為3的向量:
tapply(1:nrow(iris), iris$Species, function(ix) my.function(iris[ix, ]))
## setosa versicolor virginica
## 250 250 250
或by
:
c(by(iris, iris$Species, my.function))
## setosa versicolor virginica
## 250 250 250
或sapply/split
:
sapply(split(iris, iris$Species), my.function)
## setosa versicolor virginica
## 250 250 250
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.