R 데이터 프레임의 각 행에 대해
저는 데이터 프레임을 가지고 있습니다. 데이터 프레임의 각 행에 대해 복잡한 조회를 수행하고 일부 데이터를 파일에 추가해야 합니다.
dataFrame에는 생물학적 연구에 사용된 96개의 우물 판에서 선택된 우물에 대한 과학적 결과가 포함되어 있으므로 다음과 같은 작업을 수행하고자 합니다.
for (well in dataFrame) {
wellName <- well$name # string like "H1"
plateName <- well$plate # string like "plate67"
wellID <- getWellID(wellName, plateName)
cat(paste(wellID, well$value1, well$value2, sep=","), file=outputFile)
}
저의 시술 세계에서 저는 다음과 같은 일을 할 것입니다.
for (row in dataFrame) {
#look up stuff using data from the row
#write stuff to the file
}
이를 위한 "R 방법"은 무엇입니까?
다음 기능을 사용할 수 있습니다.
by(dataFrame, seq_len(nrow(dataFrame)), function(row) dostuff)
그러나 이렇게 행을 직접 반복하는 것은 거의 없습니다. 대신 벡터화를 시도해야 합니다.루프 내 실제 작업이 무엇을 하고 있는지 물어봐도 될까요?
기능을 사용하여 사용해 볼 수 있습니다.
> d
name plate value1 value2
1 A P1 1 100
2 B P2 2 200
3 C P3 3 300
> f <- function(x, output) {
wellName <- x[1]
plateName <- x[2]
wellID <- 1
print(paste(wellID, x[3], x[4], sep=","))
cat(paste(wellID, x[3], x[4], sep=","), file= output, append = T, fill = T)
}
> apply(d, 1, f, output = 'outputfile')
첫째, 벡터화에 대한 조나단의 지적은 옳습니다.getWellID() 함수가 벡터화되면 루프를 건너뛰고 cat 또는 write.csv:
write.csv(data.frame(wellid=getWellID(well$name, well$plate),
value1=well$value1, value2=well$value2), file=outputFile)
getWellID()가 벡터화되지 않은 경우 Jonathan의 권장 사항은 다음과 같습니다.by에 대한 오르크귀엔의 제안.apply작동해야 합니다.
그렇지 않으면, 정말로 사용하고 싶은 경우for다음과 같은 작업을 수행할 수 있습니다.
for(i in 1:nrow(dataFrame)) {
row <- dataFrame[i,]
# do stuff with row
}
사용해 볼 수도 있습니다.foreach패키지를 사용하려면 해당 구문에 익숙해야 합니다.다음은 간단한 예입니다.
library(foreach)
d <- data.frame(x=1:10, y=rnorm(10))
s <- foreach(d=iter(d, by='row'), .combine=rbind) %dopar% d
마지막 옵션은 다음 중에서 함수를 사용하는 것입니다.plyr패키지, 이 경우 규칙은 적용 기능과 매우 유사합니다.
library(plyr)
ddply(dataFrame, .(x), function(x) { # do stuff })
기본 R로 이 작업을 수행하는 가장 좋은 방법은 다음과 같습니다.
for( i in rownames(df) )
print(df[i, "column1"])
제품에 대한 이점for( i in 1:nrow(df))-어쨌든 당신은 곤경에 빠지지 않습니다.df비어 있습니다.nrow(df)=0.
나는 다음과 같은 간단한 유틸리티 기능을 사용합니다.
rows = function(tab) lapply(
seq_len(nrow(tab)),
function(i) unclass(tab[i,,drop=F])
)
또는 더 빠르고 덜 명확한 형태:
rows = function(x) lapply(seq_len(nrow(x)), function(i) lapply(x,"[",i))
이 함수는 data.frame을 행 목록으로 분할합니다.그런 다음 이 목록에 대해 일반적인 "for"를 만들 수 있습니다.
tab = data.frame(x = 1:3, y=2:4, z=3:5)
for (A in rows(tab)) {
print(A$x + A$y * A$z)
}
문제의 코드는 최소한의 수정으로 작동합니다.
for (well in rows(dataFrame)) {
wellName <- well$name # string like "H1"
plateName <- well$plate # string like "plate67"
wellID <- getWellID(wellName, plateName)
cat(paste(wellID, well$value1, well$value2, sep=","), file=outputFile)
}
비벡터화 옵션의 시간 성능이 궁금했습니다.이를 위해 knguyen으로 정의된 함수 f를 사용했습니다.
f <- function(x, output) {
wellName <- x[1]
plateName <- x[2]
wellID <- 1
print(paste(wellID, x[3], x[4], sep=","))
cat(paste(wellID, x[3], x[4], sep=","), file= output, append = T, fill = T)
}
그리고 그의 예에 있는 것과 같은 데이터 프레임:
n = 100; #number of rows for the data frame
d <- data.frame( name = LETTERS[ sample.int( 25, n, replace=T ) ],
plate = paste0( "P", 1:n ),
value1 = 1:n,
value2 = (1:n)*10 )
cat() 접근 방식을 write.table() 접근 방식과 비교하기 위해 벡터화된 두 함수(다른 함수보다 확실히 빠름)를 포함했습니다.
library("ggplot2")
library( "microbenchmark" )
library( foreach )
library( iterators )
tm <- microbenchmark(S1 =
apply(d, 1, f, output = 'outputfile1'),
S2 =
for(i in 1:nrow(d)) {
row <- d[i,]
# do stuff with row
f(row, 'outputfile2')
},
S3 =
foreach(d1=iter(d, by='row'), .combine=rbind) %dopar% f(d1,"outputfile3"),
S4= {
print( paste(wellID=rep(1,n), d[,3], d[,4], sep=",") )
cat( paste(wellID=rep(1,n), d[,3], d[,4], sep=","), file= 'outputfile4', sep='\n',append=T, fill = F)
},
S5 = {
print( (paste(wellID=rep(1,n), d[,3], d[,4], sep=",")) )
write.table(data.frame(rep(1,n), d[,3], d[,4]), file='outputfile5', row.names=F, col.names=F, sep=",", append=T )
},
times=100L)
autoplot(tm)
결과 이미지는 apply가 벡터화되지 않은 버전에 대해 최상의 성능을 제공하는 반면 write.table()은 cat()을 능가하는 것으로 보입니다. 
당신은 할 수 .by_row를 사용할 수 없습니다.purrrlyr에 사용:
myfn <- function(row) {
#row is a tibble with one row, and the same
#number of columns as the original df
#If you'd rather it be a list, you can use as.list(row)
}
purrrlyr::by_row(df, myfn)
기적으 값된은에서 된 값입니다.myfn라고 불리는 df의 새 목록 열에 들어갑니다..out.
이 여러분이이라면, 은 이이당원유출일면라력이한당은, 있다니수습쓸신것신하이는▁you▁write다▁if라고 쓸 수 있습니다.purrrlyr::by_row(df, myfn)$.out
음, 당신이 다른 언어와 동등한 R을 요구했기 때문에, 저는 이것을 하려고 했습니다.R에서 어떤 기술이 더 효율적인지는 잘 보지 못했지만 효과가 있는 것 같습니다.
> myDf <- head(iris)
> myDf
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
> nRowsDf <- nrow(myDf)
> for(i in 1:nRowsDf){
+ print(myDf[i,4])
+ }
[1] 0.2
[1] 0.2
[1] 0.2
[1] 0.2
[1] 0.2
[1] 0.4
그러나 범주형 열의 경우 필요한 경우 as.character()를 사용하여 캐스트할 수 있는 데이터 프레임이 제공됩니다.
목록 개체에 대한 작업을 수행할 수 있습니다.
data("mtcars")
rownames(mtcars)
data <- list(mtcars ,mtcars, mtcars, mtcars);data
out1 <- NULL
for(i in seq_along(data)) {
out1[[i]] <- data[[i]][rownames(data[[i]]) != "Volvo 142E", ] }
out1
아니면 데이터 프레임,
data("mtcars")
df <- mtcars
out1 <- NULL
for(i in 1:nrow(df)) {
row <- rownames(df[i,])
# do stuff with row
out1 <- df[rownames(df) != "Volvo 142E",]
}
out1
언급URL : https://stackoverflow.com/questions/1699046/for-each-row-in-an-r-dataframe
'programing' 카테고리의 다른 글
| RVM 설치 중 "gpg: command not found" 오류를 해결하는 방법은 무엇입니까? (0) | 2023.06.13 |
|---|---|
| Excel의 단일 차원 변형 배열에 있는 요소의 수 (0) | 2023.06.13 |
| IntelliJ IDEA 자동 완성 소문자 SQL (0) | 2023.06.13 |
| 명명되지 않은 구조체의 전달 선언 (0) | 2023.06.13 |
| Oracle clob 열에서 특정 문자열 검색 (0) | 2023.06.13 |