Eu tenho um quadro de dados e, para cada linha desse quadro, preciso fazer algumas pesquisas complicadas e anexar alguns dados a um arquivo.
O dataFrame contém resultados científicos para poços selecionados de placas de 96 poços usados em pesquisas biológicas, então eu quero fazer algo como:
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)
}
No meu mundo processual, eu faria algo como:
for (row in dataFrame) {
#look up stuff using data from the row
#write stuff to the file
}
Qual é a "maneira R" de fazer isso?
Respostas:
Você pode tentar isso usando a
apply()
funçãofonte
x
) é um vetor. É por isso que o exemplo acima deve usar índices numéricos; a abordagem by () fornece um data.frame, que torna seu código mais robusto.wellName <- x[1]
também poderia serwellName <- x["name"]
.Você pode usar a
by()
função:Mas iterar sobre as linhas diretamente assim raramente é o que você deseja; você deve tentar vetorizar. Posso perguntar o que o trabalho real no loop está fazendo?
fonte
1:0
não está vazioseq_len(nrow(dataFrame))
no lugar de1:nrow(dataFrame)
.dostuff
esta resposta parastr(row)
Você verá várias linhas impressas no console, começando com "'data.frame': 1 obs de x variáveis". Mas tenha cuidado, alterardostuff
pararow
não retorna um objeto data.frame para a função externa como um todo. Em vez disso, ele retorna uma lista de quadros de dados de uma linha.Primeiro, o argumento de Jonathan sobre vetorização está correto. Se sua função getWellID () for vetorizada, você poderá pular o loop e usar cat ou write.csv:
Se getWellID () não for vetorizado, a recomendação de Jonathan de usar
by
ou a sugestão de knguyen deapply
devem funcionar.Caso contrário, se você realmente quiser usar
for
, poderá fazer algo assim:Você também pode tentar usar o
foreach
pacote, embora exija que você se familiarize com essa sintaxe. Aqui está um exemplo simples:Uma opção final é usar uma função fora do
plyr
pacote; nesse caso, a convenção será muito semelhante à função aplicar.fonte
mapply(getWellId, well$name, well$plate)
.foreach
- eu vou usar esse inferno.Eu acho que a melhor maneira de fazer isso com o R básico é:
A vantagem sobre a
for( i in 1:nrow(df))
abordagem é que você não terá problemas sedf
estiver vazio enrow(df)=0
.fonte
Eu uso esta função utilitário simples:
Ou uma forma mais rápida e menos clara:
Esta função apenas divide um data.frame em uma lista de linhas. Então você pode criar um "for" normal nesta lista:
Seu código da pergunta funcionará com uma modificação mínima:
fonte
lapply
itera sobre as colunas de todo o conjunto de dadosx
, fornecendo o nome a cada colunac
e, em seguida, extraindo ai
quinta entrada desse vetor de coluna. Isso está correto?wellName <- as.character(well$name)
.Fiquei curioso sobre o desempenho temporal das opções não vetorizadas. Para esse propósito, usei a função f definida por knguyen
e um quadro de dados como o do seu exemplo:
Eu incluí duas funções vetorizadas (com certeza, mais rápidas que as outras), a fim de comparar a abordagem cat () com uma abordagem write.table () ...
A imagem resultante mostra que apply fornece o melhor desempenho para uma versão não vetorizada, enquanto write.table () parece ter um desempenho superior a cat ().
fonte
Você pode usar a
by_row
função do pacotepurrrlyr
para isso:Por padrão, o valor retornado de
myfn
é colocado em uma nova coluna da lista no df chamado.out
.Se esta é a única saída que você deseja, você pode escrever
purrrlyr::by_row(df, myfn)$.out
fonte
Bem, desde que você pediu R equivalente a outros idiomas, tentei fazer isso. Parece funcionar, embora eu realmente não tenha examinado qual técnica é mais eficiente em R.
Porém, para as colunas categóricas, você buscaria um Quadro de Dados que você poderia criar usando as.character (), se necessário.
fonte