#r #function #dataframe
#r #функция #фрейм данных
Вопрос:
У меня есть следующий код внутри функции
Myfunc<- function(directory, MyFiles, id = 1:332) {
# uncomment the 3 lines below for testing
#directory<-"local"
#id=c(2, 4)
#MyFiles<-c(f2.csv,f4.csv)
idd<-id
df2 <- data.frame()
for(i in 1:length(idd)) {
EmptyVector <- read.csv(MyFiles[i])
comp_cases[i]<-sum(complete.cases(EmptyVector))
print(comp_cases[[i]])
id=idd[i]
ret2=comp_cases[[i]]
df2<-rbind(df2,data.frame(id,ret2))
}
print(df2)
return(df2)
}
Это работает, когда я пытаюсь запустить его в R, выбирая код внутри функции и комментируя возврат. Я получаю хороший фрейм данных, например, из инструкции print:
> df2
id ret2
1 2 994
2 4 7112
Однако, когда я пытаюсь вернуть df2
фрейм данных из функции, он возвращает только 1-ю строку, игнорируя все остальные значения. Моя проблема в том, что он работает внутри функции для различных значений, которые я пробовал (открытие нескольких файлов с различными комбинациями), а не когда я пытаюсь вернуть фрейм данных. Может кто-нибудь помочь, пожалуйста. Заранее большое спасибо.
Комментарии:
1. Как вы вызываете свою функцию?
Ответ №1:
Если я вас правильно понимаю, вы пытаетесь создать фрейм данных с количеством завершенных обращений для каждого id
. Предположим, что ваши файлы представляют собой имена с идентификаторами, подобными указанным вами (например f2.csv
), вы можете упростить свою функцию следующим образом:
myfunc <- function(directory, id = 1:332) {
y <- vector()
for(i in 1:length(id)){
x <- id
y <- c(y, sum(complete.cases(
read.csv(as.character(paste0(directory,"/","f",id[i],".csv"))))))
}
df <- data.frame(x, y)
colnames(df) <- c("id","ret2")
return(df)
}
Вы можете вызвать эту функцию следующим образом:
myfunc("name-of-your-directory",25:87)
Объяснение приведенного выше кода. Вы должны разбить свою проблему на этапы:
- Вам нужен вектор идентификаторов, это делается с помощью
x <- id
- Для каждого
id
вы хотите количество завершенных обращений. Чтобы получить это, вы должны сначала прочитать файл. Это делается с помощьюread.csv(as.character(paste0(directory,"/","f",id[i],".csv")))
. Чтобы получить количество полных обращений к этому файлу, вы должны обернутьread.csv
код внутриsum
иcomplete.cases
. - Теперь вы хотите добавить это число к вектору. Поэтому вам нужен пустой вектор (
y <- vector()
), к которому вы можете добавить количество завершенных обращений с шага 2. Это делается путем переноса кода с шага 2 внутрьy <- c(y, "code step 2")
. При этом вы добавляете количество полных обращений для каждогоid
к векторуy
. - Последним шагом является объединение этих двух векторов в фрейм данных с
df <- data.frame(x, y)
помощью и присвоение некоторого значенияcolnames
.
Включив шаги 1, 2 и 3 (кроме y <- vector()
части) в цикл for, вы можете перебирать список указанных идентификаторов. Создание пустого вектора с y <- vector()
помощью должно быть выполнено перед циклом for, чтобы цикл for мог добавлять значения y
.
Комментарии:
1. @Japp — Это отлично сработало. Код намного чище. Да, я пытался вернуть фрейм данных полных обращений с идентификатором. Если вы скажете мне, где я ошибся, это все равно поможет.
2. @user3127034 — Основная часть, в которой вы ошиблись, — это включение
Myfiles
параметра в вашу функцию. Это было не нужно, поскольку все ваши имена файлов имеют одинаковую структуру и могут быть получены из идентификаторов. Я добавил объяснение. Я надеюсь, что это поможет.
Ответ №2:
Это на самом деле довольно легко обойти, изменив область видимости.
Проблема в том, что сначала вы создаете исходный фрейм данных как локальную переменную, затем вы просто меняете местами строки, так что в итоге вы получите только первый и последний результаты в фрейме данных.
Когда я создаю цикл for с помощью R и хочу добавить результаты последовательных запросов и т.д. для некоторого начального фрейма данных я делаю это:
function(<some_args>){
main_dataframe <<- do something to generate the first set of results from
whatever you want to iterate, like 1:10, a given list, etc. and create the
initial dataframe from the first iteration and use the global assignment
('<<-'), not '<-' or '='
main_dataframe <<- do_something(whatever_you're_iterating_over[1])
for (i in 2:length(whatever_you're_iterating_over)) {
next_dataframe = do_something(whatever_you're_iterating_over[i])
main_dataframe <<- rbind(main_dataframe, next_dataframe)
}
}
Область видимости позволит каждой итерации создавать фрейм данных, который вы можете добавить к оригиналу, не теряя ни одной итерации между первой и последней.
Комментарии:
1. спасибо за упоминание
<<-
глобального оператора присваивания. Это было полезно в моем контексте