2015-06-29 2 views
0

Все еще относительно новое для R. Попытка иметь динамические переменные в цикле, но сталкивается со всеми видами проблем. Первоначальный код выглядит примерно так (но больше)R переменные имена в цикле, get и т. Д.

data.train$Pclass_F <- as.factor(data.train$Pclass) 
data.test$Pclass_F <- as.factor(data.test$Pclass) 

, который я пытаюсь построить в петлю, представляя себе что-то вроде этого

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    i$Pclass_F <- as.factor(i$Pclass) 
} 

, который не работает. Небольшое исследование подразумевает, что для преобразования строки datalist в переменную мне нужно использовать функцию get. Поэтому моя следующая попытка была

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    get(i$Pclass_F) <- as.factor(get(i$Pclass)) 
} 

который все еще не работает Error in i$Pclass : $ operator is invalid for atomic vectors. Протестировано

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    get(i)$Pclass_F <- as.factor(get(i)$Pclass) 
} 

который все еще не работает Error in get(i)$Pclass_F <- as.factor(get(i)$Pclass) : could not find function "get<-". Даже попробовал

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    get(i[Pclass_F]) <- as.factor(get(i[Pclass])) 
} 

который все еще не работает Error in get(i[Pclass]) : object 'Pclass' not found. Испытанный

datalist <- c("data.train", "data.test") 
for (i in datalist){ 
    get(i)[Pclass_F] <- as.factor(get(i)[Pclass]) 
} 

, который до сих пор не работает Error in '[.data.frame'(get(i), Pclass) : object 'Pclass' not found

Теперь понял, что никогда не были включены данные, так что никто не может запустить это сами, но только, чтобы показать, что это не проблема данных

> class(data.train$Pclass) 
[1] "integer" 
> class(data.test$Pclass) 
[1] "integer" 
> datalist 
[1] "data.train" "data.test" 
+8

Остановите структурирование кода вокруг 'get'. Запретите это из своего лексикона, пока вы не окажетесь намного лучше в R. В любое время вы считаете «динамическую переменную», останавливаете и создаете именованный список. Поместите их в фактический список и используйте индексирование: 'L <- list (data.train = data.train, data.test = data.test)'. – joran

+1

Я согласен, что это ужасное кодирование. Не в первый раз я вижу это на SO. Я действительно удивляюсь, откуда берутся эти плохие привычки, и как они получили «интуитивный» и «естественный» для ОП. Я думаю, что это точка зрения (и основная) для решения. –

+2

@ColonelBeauvel Я бы не стал слишком тяжелым на OP. Быть новичком обычно означает просто пытаться найти что-то, что «работает», и вы узнаете, является ли оно «хорошим» в этом процессе. Я нахожу эту конкретную проблему расстраивающей, потому что она часто встречается, но случай использования каждого человека настолько отличается, что очень сложно написать один всеобъемлющий ресурс, который эффективно отводит людей от 'get' и' assign'. – joran

ответ

4

проблема, связанная с тем, как кадры данных и большинство других объектов обрабатываются в R. Во многих языках программирования объекты (или, по крайней мере, могут быть) переданы в функции по ссылке. В C++, если я передаю указатель на объект функции, которая управляет этим объектом, оригинал будет изменен. Это не так, как вещи работают по большей части в R.

Когда объект создается следующим образом:

x <- list(a = 5, b = 9) 

А потом скопировали, как это:

y <- x 

Первоначально y и x будет указывать на один и тот же объект в ОЗУ. Но как только y будет вообще изменен, будет создана копия. Поэтому назначение y$c <- 12 не влияет на x.

get() не возвращает именованный объект таким образом, который может быть изменен без предварительного присвоения ему другой переменной (что означает, что исходная переменная остается неизменной).

Правильный способ выполнения этого в R заключается в хранении ваших кадров данных с именем list. Затем вы можете прокручивать список и использовать синтаксис замены для изменения столбцов.

datalist <- list(data.train = data.train, data.test = data.test) 
for (df in names(datalist)){ 
    datalist[[df]]$Pclass_F <- as.factor(datalist[[df]]$Pclass_F) 
} 

Вы также можете использовать:

datalist <- setNames(lapply(list(data.train, data.test), function(data) { 
    data$Pclass_Fb <- as.factor(data$Pclass_Fb) 
    data 
}), c("data.train", "data.test")) 

Это использует lapply для обработки каждого элемента списка, возвращая новый список с измененными столбцами.

В теории вы могли бы достичь того, что изначально пытались сделать, используя оператор [[ в глобальной среде, но это был бы необычный способ сделать что-то и может привести к путанице позже.

+0

Благодаря @Nick KI был придумайте что-то подобное себе, но в первом примере он добавляет столбец в dataframes в списке, а не в самих самих dataframes. Если я посмотрю на 'head (data.train)', я не вижу новый столбец, но если я посмотрю на 'head (datalist [[1]]), я могу. –

+3

@SC. это то, что я пытался понять. Если вы не используете '[[' в глобальной среде, вы не можете делать то, что вы хотите достичь, с помощью data.frames в глобальной среде. Вам нужно сохранить их в списке или среде, и вообще я бы использовал список для этого варианта использования. Затем вы можете обращаться к ним как 'datalist $ data.train' и использовать их в циклах и т. Д., Как показано здесь. В качестве альтернативы вы могли бы, конечно, просто использовать отдельные инструкции для каждого файла data.frame (как в начале вашего ответа), и если вы обрабатываете более одного столбца из этой части кода в функции. –

+0

Спасибо @ Ник. Наверное, это то, о чем говорил @joran, но я не понимал. Таким образом, в этом случае список 'datalist' становится моей основной структурой данных. Это интересная концепция, о которой я не думал. Это приведет к тому, что некоторые имена будут длинными 'datalist $ data.train $ Pclass' и т. Д., Но это должно сработать. Я полагаю, что это лучшая практика и хорошая привычка подбирать меня? –

Смежные вопросы