각 행의 여러 인수를 사용하여 각 데이터 프레임 행에 적용 유사 함수 호출
여러 개의 열이 있는 데이터 프레임이 있습니다.데이터 프레임의 각 행에 대해 해당 행의 함수를 호출하고, 해당 함수의 입력은 해당 행의 여러 열을 사용합니다.예를 들어, 이 데이터와 두 개의 인수를 허용하는 testFunc가 있다고 가정해 보겠습니다.
> df <- data.frame(x=c(1,2), y=c(3,4), z=c(5,6))
> df
x y z
1 1 3 5
2 2 4 6
> testFunc <- function(a, b) a + b
예를 들어 x열과 z열에 이 테스트 Func를 적용하려고 합니다.그래서 1행은 1+5, 2행은 2+6을 원합니다. 적용 함수 계열을 사용하여 for 루프를 작성하지 않고 이 작업을 수행할 수 있는 방법이 있습니까?
시도해 봤습니다.
> df[,c('x','z')]
x z
1 1 5
2 2 6
> lapply(df[,c('x','z')], testFunc)
Error in a + b : 'b' is missing
하지만 오류가 있어요, 아이디어 있어요?
EDIT: 제가 부르고 싶은 실제 기능은 단순한 합계가 아니라 power.t.t.test입니다.저는 a+b를 예시용으로만 사용했습니다.최종 목표는 다음과 같은 작업을 수행할 수 있는 것입니다(의사 코드로 작성됨).
df = data.frame(
delta=c(delta_values),
power=c(power_values),
sig.level=c(sig.level_values)
)
lapply(df, power.t.test(delta_from_each_row_of_df,
power_from_each_row_of_df,
sig.level_from_each_row_of_df
))
여기서 결과는 df의 각 행에 대한 power.t.t.t.test에 대한 출력 벡터입니다.
신청할 수 있습니다apply
원본 데이터의 하위 집합으로 이동합니다.
dat <- data.frame(x=c(1,2), y=c(3,4), z=c(5,6))
apply(dat[,c('x','z')], 1, function(x) sum(x) )
또는 함수가 단지 합일 경우 벡터화된 버전을 사용합니다.
rowSums(dat[,c('x','z')])
[1] 6 8
당신이 경우용을 사용하고 .testFunc
testFunc <- function(a, b) a + b
apply(dat[,c('x','z')], 1, function(x) testFunc(x[1],x[2]))
편집 색인이 아닌 이름으로 열에 액세스하려면 다음과 같은 작업을 수행할 수 있습니다.
testFunc <- function(a, b) a + b
apply(dat[,c('x','z')], 1, function(y) testFunc(y['z'],y['x']))
A data.frame
입니다.list
그래서...
벡터화된 함수의 경우 do.call
보통 좋은 내기입니다.하지만 논쟁의 이름이 등장합니다. 당신의 기여당입니다.testFunc
a와 b 대신에 args x와 y를 사용하여 호출됩니다. 그...
를 발생시키지 관련 를 전달할 수 합니다.
do.call( function(x,z,...) testFunc(x,z), df )
벡터화되지 않은 기능의 경우,mapply
사용할 수 있지만, 인수의 순서와 일치하거나 명시적으로 이름을 지정해야 합니다.
mapply(testFunc, df$x, df$z)
은 씩끔가.apply
모든 인수가 동일한 유형일 때처럼 강제로 작동합니다.data.frame
행렬로 변환하면 데이터 유형이 변경되어 문제가 발생하지 않습니다.당신의 예는 이런 종류의 것이었습니다.
인수가 모두 전달되는 다른 함수 내에서 함수를 호출하려면 이들보다 훨씬 교묘한 방법이 있습니다.신체의 첫 번째 라인을 연구합니다.lm()
당신이 그 길을 가고 싶다면요.
사용하다mapply
> df <- data.frame(x=c(1,2), y=c(3,4), z=c(5,6))
> df
x y z
1 1 3 5
2 2 4 6
> mapply(function(x,y) x+y, df$x, df$z)
[1] 6 8
> cbind(df,f = mapply(function(x,y) x+y, df$x, df$z) )
x y z f
1 1 3 5 6
2 2 4 6 8
으로 새로운 :dplyr
적용할 함수가 벡터화된 경우 다음을 사용할 수 있습니다.mutate
의 dplyr
패키지:
> library(dplyr)
> myf <- function(tens, ones) { 10 * tens + ones }
> x <- data.frame(hundreds = 7:9, tens = 1:3, ones = 4:6)
> mutate(x, value = myf(tens, ones))
hundreds tens ones value
1 7 1 4 14
2 8 2 5 25
3 9 3 6 36
이 있는 오래된 :plyr
그 는 저의겸의는로한으, 그일가적도는구한합장입니다.mdply
plyr
꾸러미
예:
> library(plyr)
> x <- data.frame(tens = 1:3, ones = 4:6)
> mdply(x, function(tens, ones) { 10 * tens + ones })
tens ones V1
1 1 4 14
2 2 5 25
3 3 6 36
불행히도 Bertjan Broeksema가 지적했듯이, 만약 당신이 데이터 프레임의 모든 열을 사용하지 않는다면, 이 접근법은 실패합니다.mdply
예를 , "", "", ", ", ", ",
> library(plyr)
> x <- data.frame(hundreds = 7:9, tens = 1:3, ones = 4:6)
> mdply(x, function(tens, ones) { 10 * tens + ones })
Error in (function (tens, ones) : unused argument (hundreds = 7)
다른 사람들은 올바르게 지적했습니다.mapply
이 목적을 위해 만들어졌지만, (완전성을 위해) 개념적으로 더 간단한 방법은 단지 사용하는 것입니다.for
리고리고▁loop..
for (row in 1:nrow(df)) {
df$newvar[row] <- testFunc(df$x[row], df$z[row])
}
되어 있기 . (둘 다 많함가이벡필반없있습요다니가복할로으므어되미화터수은ither▁many없ne▁are다습니▁(필ationsization요▁need반가▁iter).for
또는 프루또는*pply
함수)를 선택합니다.당신의.testFunc
그러한 예 중 하나입니다.간단히 전화할 수 있습니다.
testFunc(df[, "x"], df[, "z"])
일반적으로 이러한 벡터화 접근 방식을 먼저 시도하고 원하는 결과가 나오는지 확인하는 것이 좋습니다.
해야 할 , "" "" "" "" "" "" "" " "" " " " " " " " " " " " " " " "mapply
있는 도 있습니다: 다과같은기사수용있할다습니능을음▁might다.
mapply(power.t.test, df[, "x"], df[, "z"])
여기 다른 접근법이 있습니다.그것은 더 직관적입니다.
답변 중 일부를 고려하지 않은 것으로 생각되는 핵심 측면 중 하나는 나중에 사용자가 행 계산을 쉽게 수행할 수 있도록 하는 것입니다(). 행렬(모든 숫자) 데이터에 대해서만 적용할 수 있습니다.
데이터 프레임에 대해서는 여전히 열에 대한 작업이 가능합니다.
as.data.frame(lapply(df, myFunctionForColumn()))
행에서 작동하려면 먼저 전치를 수행합니다.
tdf<-as.data.frame(t(df))
as.data.frame(lapply(tdf, myFunctionForRow()))
단점은 R이 당신의 데이터 테이블을 복사할 것이라고 생각합니다.기억력 문제일 수도 있습니다.(이것은 정말 슬픈 일입니다. 왜냐하면 tdf가 원래 df에 대한 반복기이기 때문에 메모리를 절약할 수 있지만 R은 포인터나 반복기 참조를 허용하지 않기 때문입니다.)
또한 관련 질문은 데이터 프레임의 각 개별 셀에서 작동하는 방법입니다.
newdf <- as.data.frame(lapply(df, function(x) {sapply(x, myFunctionForEachCell()}))
data.table
이를 위한 직관적인 방법도 있습니다.
library(data.table)
sample_fxn = function(x,y,z){
return((x+y)*z)
}
df = data.table(A = 1:5,B=seq(2,10,2),C = 6:10)
> df
A B C
1: 1 2 6
2: 2 4 7
3: 3 6 8
4: 4 8 9
5: 5 10 10
그:=
안에 새할 수 .
df[,new_column := sample_fxn(A,B,C)]
> df
A B C new_column
1: 1 2 6 18
2: 2 4 7 42
3: 3 6 8 72
4: 4 8 9 108
5: 5 10 10 150
또한 다음 방법을 사용하면 상수를 인수로 쉽게 받아들일 수 있습니다.
df[,new_column2 := sample_fxn(A,B,2)]
> df
A B C new_column new_column2
1: 1 2 6 18 6
2: 2 4 7 42 12
3: 3 6 8 72 18
4: 4 8 9 108 24
5: 5 10 10 150 30
@user20877984의 답변은 훌륭합니다.그들이 제 이전 답변보다 훨씬 더 잘 요약했기 때문에, 여기 개념을 적용하려는 저의 (아마도 여전히 엉터리일 것입니다) 시도가 있습니다.
용사를 합니다.do.call
기본적인 방식으로:
powvalues <- list(power=0.9,delta=2)
do.call(power.t.test,powvalues)
전체 데이터 세트에서 작업:
# get the example data
df <- data.frame(delta=c(1,1,2,2), power=c(.90,.85,.75,.45))
#> df
# delta power
#1 1 0.90
#2 1 0.85
#3 2 0.75
#4 2 0.45
lapply
그자리의 power.t.test
지정된 값의 각 행에 대한 함수:
result <- lapply(
split(df,1:nrow(df)),
function(x) do.call(power.t.test,x)
)
> str(result)
List of 4
$ 1:List of 8
..$ n : num 22
..$ delta : num 1
..$ sd : num 1
..$ sig.level : num 0.05
..$ power : num 0.9
..$ alternative: chr "two.sided"
..$ note : chr "n is number in *each* group"
..$ method : chr "Two-sample t test power calculation"
..- attr(*, "class")= chr "power.htest"
$ 2:List of 8
..$ n : num 19
..$ delta : num 1
..$ sd : num 1
..$ sig.level : num 0.05
..$ power : num 0.85
... ...
저는 정역 함수 이름을 찾으러 왔습니다. - 존재한다는 것을 알고 있었습니다.(나의) 향후 참조를 위해 그리고 다음을 위해 이것을 추가하는 것.tidyverse
매니아:purrrlyr:invoke_rows
(purrr:invoke_rows
이전 버전에서는).
원래 질문과 같이 표준 통계 방법에 연결하면 브룸 패키지가 도움이 될 것입니다.
data.frame 열이 서로 다른 유형이면apply()
문제가 있습니다.행 반복에 대한 미묘함은 다음과 같습니다.apply(a.data.frame, 1, ...)
열이 서로 다른 유형(예: 요인 및 숫자 열)인 경우 암시적 형식을 문자 형식으로 변환합니다.다음은 하나의 열에 요인을 사용하여 숫자 열을 수정하는 예제입니다.
mean.height = list(BOY=69.5, GIRL=64.0)
subjects = data.frame(gender = factor(c("BOY", "GIRL", "GIRL", "BOY"))
, height = c(71.0, 59.3, 62.1, 62.1))
apply(height, 1, function(x) x[2] - mean.height[[x[1]]])
열이 문자 형식으로 변환되기 때문에 뺄셈이 실패합니다.
한 가지 해결책은 두 번째 열을 숫자로 역변환하는 것입니다.
apply(subjects, 1, function(x) as.numeric(x[2]) - mean.height[[x[1]]])
그러나 열을 분리하고 사용하면 변환을 피할 수 있습니다.mapply()
:
mapply(function(x,y) y - mean.height[[x]], subjects$gender, subjects$height)
mapply()
한 이유는 필한이유 때문입니다.[[ ]]
벡터 인수를 사용할 수 없습니다.따라서 열 반복은 다음으로 벡터를 전달함으로써 뺄셈 전에 수행될 수 있습니다.[]
조금 더 추악한 코드로:
subjects$height - unlist(mean.height[subjects$gender])
정말 은 이을위정좋기능은은말한입니다.adply
plyr
특히 원본 데이터 프레임에 결과를 추가하려는 경우.와 그 인 이와함그사촌수▁and▁this사.ddply
많은 두통과 코드 줄을 아꼈습니다!
df_appended <- adply(df, 1, mutate, sum=x+z)
또는 원하는 기능을 호출할 수 있습니다.
df_appended <- adply(df, 1, mutate, sum=testFunc(x,z))
언급URL : https://stackoverflow.com/questions/15059076/call-apply-like-function-on-each-row-of-dataframe-with-multiple-arguments-from-e
'programing' 카테고리의 다른 글
WHERE 콜인(...) 조건에 대한 제한 (0) | 2023.06.25 |
---|---|
HTTP 오류 503.서비스를 사용할 수 없습니다.웹 사이트에 액세스할 때 앱 풀이 중지됨 (0) | 2023.06.25 |
Spring Boot에서 종속성을 선택적으로 업그레이드하는 방법? (샘플 케이스: Spring Data) (0) | 2023.06.20 |
Mongodb 존재하지 않는 경우에만 삽입하는 방법(존재하는 경우 업데이트 없음)? (0) | 2023.06.20 |
파이썬에서 인쇄 대신 로깅을 사용하는 이유는 무엇입니까? (0) | 2023.06.20 |