У меня есть фрейм данных, и для каждой строки в этом фрейме мне нужно выполнить несколько сложных поисков и добавить некоторые данные в файл.
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» для этого?
Ответы:
Вы можете попробовать это, используя
apply()
функциюисточник
x
) - вектор. Вот почему в приведенном выше примере должны использоваться числовые индексы; подход by () дает вам data.frame, который делает ваш код более надежным.wellName <- x[1]
тоже может бытьwellName <- x["name"]
.Вы можете использовать
by()
функцию:Но итерации по строкам напрямую, как это редко бывает то, что вы хотите; вы должны попытаться векторизовать вместо этого. Могу я спросить, что делает настоящая работа в цикле?
источник
1:0
он не пустойseq_len(nrow(dataFrame))
вместо1:nrow(dataFrame)
.dostuff
в этом ответе наstr(row)
Вы увидите несколько строк, напечатанных в консоли, начинающихся с "'data.frame': 1 obs of x variable". Но будьте осторожны, переходdostuff
наrow
не возвращает объект data.frame для внешней функции в целом. Вместо этого он возвращает список однорядных фреймов данных.Во-первых, точка зрения Джонатана о векторизации верна. Если ваша функция getWellID () векторизована, то вы можете пропустить цикл и просто использовать cat или write.csv:
Если getWellID () не векторизован, то рекомендация Джонатана об использовании
by
или предложение knguyen'аapply
должны сработать.В противном случае, если вы действительно хотите использовать
for
, вы можете сделать что-то вроде этого:Вы также можете попробовать использовать
foreach
пакет, хотя он требует, чтобы вы ознакомились с этим синтаксисом. Вот простой пример:Последний вариант - использовать функцию из
plyr
пакета, и в этом случае соглашение будет очень похоже на функцию apply.источник
mapply(getWellId, well$name, well$plate)
.foreach
- я собираюсь использовать ад из этого.Я думаю, что лучший способ сделать это с базовым R это:
Преимущество перед
for( i in 1:nrow(df))
-approach заключается в том, что вы не попадете в беду, еслиdf
пусто иnrow(df)=0
.источник
Я использую эту простую служебную функцию:
Или более быстрая, менее понятная форма:
Эта функция просто разбивает data.frame на список строк. Затем вы можете сделать нормальное «для» над этим списком:
Ваш код из вопроса будет работать с минимальной модификацией:
источник
lapply
выполняет итерации по столбцам всего набора данныхx
, присваивая каждому столбцу имяc
, а затем извлекаяi
th-ую запись из этого вектора столбца. Это верно?wellName <- as.character(well$name)
.Мне было любопытно узнать время исполнения не векторизованных опций. Для этой цели я использовал функцию f, определенную knguyen
и фрейм данных, подобный тому, что в его примере:
Я включил две векторизованные функции (наверняка быстрее, чем другие), чтобы сравнить подход cat () с функцией write.table () ...
Полученное изображение показывает, что применение дает лучшую производительность для не векторизованной версии, тогда как write.table (), кажется, превосходит cat ().
источник
Вы можете использовать
by_row
функцию из пакетаpurrrlyr
для этого:По умолчанию возвращаемое значение from
myfn
помещается в новый столбец списка в вызываемой df.out
.Если это единственный выход, который вы хотите, вы можете написать
purrrlyr::by_row(df, myfn)$.out
источник
Ну, так как вы попросили R эквивалентно другим языкам, я попытался сделать это. Кажется, работает, хотя я на самом деле не смотрел, какая техника более эффективна в R.
Тем не менее, для категориальных столбцов он выберет вам фрейм данных, который вы можете набрать, используя as.character () при необходимости.
источник