Цикл R не может распознать объект, который я уже создал в том же цикле - PullRequest
3 голосов
/ 22 марта 2011

Я бы хотел задать вам вопрос еще раз, если у вас есть время.

Я представляю вам мой обычный df-фрейм данных, который я уже использовал ранее в моих предыдущих квестах, как преобразованную, упрощенную версию моегореальный df dataframe, который было бы слишком сложно показать здесь.Однако основные характеристики все те же.

id <-c(1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3)
a <-c(3,1,3,3,1,3,3,3,3,1,3,2,1,2,1,3,3,2,1,1,1,3,1,3,3,3,2,1,1,3)
b <-c(3,2,1,1,1,1,1,1,1,1,1,2,1,3,2,1,1,1,2,1,3,1,2,2,1,3,3,2,3,2)
c <-c(1,3,2,3,2,1,2,3,3,2,2,3,1,2,3,3,3,1,1,2,3,3,1,2,2,3,2,2,3,2)
d <-c(3,3,3,1,3,2,2,1,2,3,2,2,2,1,3,1,2,2,3,2,3,2,3,2,1,1,1,1,1,2)
e <-c(2,3,1,2,1,2,3,3,1,1,2,1,1,3,3,2,1,1,3,3,2,2,3,3,3,2,3,2,1,4)
df <-data.frame(id,a,b,c,d,e)
df
df.list <- lapply(df[,2:6],function(x, id){ t(table(x, id, useNA = "ifany")) }, df$id)
df.list

Видите ли, в основном то, что я создал здесь, представляет собой коллекцию общей суммы вхождений каждого различного числа в столбцах «a» - «e».'и сгруппированы по идентификаторам в столбце id одновременно.

На следующем шаге я создал цикл, который выглядит следующим образом:

for (i in names(df.list))
{
  df.list[i]
  assign( paste("var",i,sep=""),
          (matrix(matrix(unlist(df.list[i])),ncol=nlevels(factor(df[,i])),nrow=3))/10
        )
}

Он делит каждый элементсписок, созданный ранее 10. Тем не менее, это только первая половина моего всего цикла, которую я хотел реализовать, но, по крайней мере, он ЕЩЕ работает нормально и нормально, у меня нет проблем с этим, просто отправьте эти коды в R здесь ->

vara
varb
varc
vard
vare

Теперь более сложная часть наступает сейчас, когда я пытаюсь выполнить раздел «for (k in 1: 3)».Итак, давайте попробуем снова отправить эти строки (а также предыдущую половину части всего цикла).

for (i in names(df.list))
{
  df.list[i]
  assign( paste("var",i,sep=""),
          (matrix(matrix(unlist(df.list[i])),ncol=nlevels(factor(df[,i])),nrow=3))/10
        )

  for (k in 1:3)
    assign( paste("var",i,k,sep="."),
            vari[k,]*5 
          )
}

Моя проблема в строке vari[k,]*5.(В действительности я должен разобраться с умножением матриц на этом этапе.) Код не распознает переменные, однако я уже определил i ранее.И я не собираюсь использовать vara, varb, varc ... и т. Д., Потому что мне нужно, чтобы это было автоматизировано.Причина: мне придется регулярно обновлять мой реальный файл данных df, поэтому число переменных может со временем меняться (у меня не обязательно будут переменные только от a до e, скорее a до f или a до y и т. Д.

Итак, я получаю следующее сообщение об ошибке:

Error in assign(paste("var", i, k, sep = "."), vari[k, ] * 5): object 'vari' not found

Что я здесь пропускаю / делаю неправильно? Я просто хочу сослаться надругой объект, который я уже создал в том же цикле, но все еще не могу распознать. Есть ли здесь правильное решение?

Большое спасибо

Ответы [ 3 ]

1 голос
/ 22 марта 2011

@ хадли, я бы согласился.Из того, что я видел, векторизация циклов - почти всегда правильный ответ.

@ lazlo Посмотрите на эти примеры: Векторизация цикла и Кодирование R-рейта -избегая цикла for

1 голос
/ 22 марта 2011
1000 * vari действительно не распознается, так как вы сохранили vara, varb, varc, vard, ... но не vari. здесь i в имени НЕ заменяется на число!

То, что вы хотите достичь, может быть легко сделано:

lapply(df.list,function(i) i/10*5)

Полагаю, это всего лишь пример, и ваш реальный код более сложный. Но все же, просто используйте lapply и имейте в виду, что таблица - это матрица. Все эти unlist / матричные вещи совершенно не нужны.

> is.matrix(df.list[[1]])
[1] TRUE

Если вы действительно, действительно хотите удалить атрибуты таблицы и хотите дать указанные имена, тогда ваш код можно упростить до:

VarList <- sapply(names(df.list),function(i){
  out <- df.list[[i]]/10*5

  out <- matrix(out,ncol(out)) # in case you want to drop all table attributes

  colnames(out) <- paste(
                     paste("var",i,sep=""),
                     1:ncol(out),
                     sep=".")
  out
},USE.NAMES=TRUE,simplify=FALSE)

Который дает вам список матриц, где имена переменных формируются так, как вы хотите. Это также позволяет вам сделать что-то вроде

> VarList[["d"]][,1:2]
     vard.1 vard.2
[1,]    1.0    1.5
[2,]    1.0    3.0
[3,]    2.5    1.5

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

1 голос
/ 22 марта 2011

Думаю, вы можете заменить

vari[k,]*5 

на

get( paste( "var", i, sep="" ) )*5 

Вам действительно нужно создавать переменные таким образом?Я беспокоюсь о том, что пространство имен выйдет из-под контроля, если ваш набор данных станет больше.Может быть, лучше просто создать объект списка или определить собственную среду с помощью new.env и установить переменные в этой среде вместо глобальной?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...