Страница 1 из 1
передать переменную, а не character
Добавлено: 02 ноя 2010, 17:38
Анна
бьюсь второй день c R и не могу элементарную вещь сделать. Как в R сделать так, чтобы он воспринимал слово как переменную, а не как character?
name <- "index1"
mylist$name <- c(1:10)
вот так он думает что name - это слово такое, а можно ли как сделать так, чтобы он считывал значение переменной и его вставлял? чтобы в результате было
mylist$index1
рабочий пример и приложения (файлы species.txt, var.txt, и данные - ferganaalt.csv)
Код: Выделить всё
readcsv<-function(varlist, specieslist){
species<-read.table("species.txt",header=FALSE)
species$V1 <- as.character(species$V1)
variab<-read.table("var.txt",header=FALSE)
variab$V1 <- as.character(variab$V1)
mylist = NULL
for j in 1:nrow(variab) {
#import $species$var.csv
afile<-paste(species$V1[i],variab$V1[j],".csv",sep="")
adata<-read.csv(afile,header=FALSE)
#calculate column weight - percentage of cells occupied by particular value
V5<-unlist(lapply(adata$V2, function(x) (100*x)/sum(adata$V2)))
adata<-cbind(adata,V5)
#normalized values
V6<-(adata$V4/adata$V5)
adata<-cbind(adata,V6)
#cumsum
V7<-cumsum(adata$V6)
adata<-cbind(adata,V7)
#export variable into list
var_t<-paste(variab$V1[j],"_v", sep="")
#### ПРОБЛЕМА ВОТ ЗДЕСЬ - код не воспринимает var_t как переменную, а думает что это - character
mylist$var_t = adata$V7
}
}
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 17:46
Максим Дубинин
Есть пара способов, прости я не стал смотреть в сам скрипт и данные, скажи если что-то непонятно, я могу глянуть более подробно:
Первый
Код: Выделить всё
name <- "index1"
d = data.frame(sample(1:10,10),sample(1:10,10))
names(d) <- paste("index",1:2,sep="")
d[name]
Второй способ, возможно более внятный, сначала по имени найти позицию поля:
Код: Выделить всё
name <- "index1"
d = data.frame(sample(1:10,10),sample(1:10,10))
names(d) <- paste("index",1:2,sep="")
fpos = which(names(d) == name)
d[fpos]
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 18:04
Анна
спасибо!
а как сделать так, чтобы именно имя присваивалось из переменной?
Код: Выделить всё
d = data.frame(sample(1:10,10),sample(1:10,10))
names(d) <- paste("index",1:2,sep="")
var_t<-paste(d$index1[1],"_v", sep="")
mylist$var_t = d$index2
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 18:30
Максим Дубинин
хм, то что ты называешь листом это фрейм данных, лист - совсем другая структура в R
В твоем случае гораздо проще собрать фрейм, а потом назначать ему названия полей.
Я позволил себе довольно немного переписать твой скрипт:
Код: Выделить всё
species = scan("D:\\Programming\\R\\var-as-text\\species.txt",what="character")
variab <- scan("D:\\Programming\\R\\var-as-text\\var.txt",what="character")
mylist = data.frame(0)
for (i in 1:length(variab)) {
#import $species$var.csv
afile<-paste("D:\\Programming\\R\\var-as-text\\",species[i],variab[i],".csv",sep="")
d<-read.csv(afile,header=FALSE)
#calculate column weight - percentage of cells occupied by particular value
V5<-unlist(lapply(d$V2, function(x) (100*x)/sum(d$V2)))
d<-cbind(d,V5)
#normalized values
V6<-(d$V4/d$V5)
d<-cbind(d,V6)
#cumsum
V7<-cumsum(d$V6)
d<-cbind(d,V7)
#export variable into list
var_t<-paste(variab[i],"_v", sep="")
#### ПРОБЛЕМА ВОТ ЗДЕСЬ - код не воспринимает var_t как переменную, а думает что это - character
mylist = cbind(mylist,d$V7)
names(mylist)[i+1] = var_t
}
mylist = mylist[,-1]
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 18:45
Анна
нет, нет! у меня именно что пустой лист, куда я в цикле хочу добавлять колонки с данными, и проблема в том, что названия этих колонок у меня идут из переменных. можно как то с листом справиться?
лист у меня от того, что cumsum разной длины и поэтому датафрейм не получится
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 18:53
Максим Дубинин
Пардоньте

Переделка под листы:
Код: Выделить всё
species = scan("D:\\Programming\\R\\var-as-text\\species.txt",what="character")
variab <- scan("D:\\Programming\\R\\var-as-text\\var.txt",what="character")
mylist = list()
for (i in 1:length(variab)) {
#import $species$var.csv
afile<-paste("D:\\Programming\\R\\var-as-text\\",species[i],variab[i],".csv",sep="")
d<-read.csv(afile,header=FALSE)
#calculate column weight - percentage of cells occupied by particular value
V5<-unlist(lapply(d$V2, function(x) (100*x)/sum(d$V2)))
d<-cbind(d,V5)
#normalized values
V6<-(d$V4/d$V5)
d<-cbind(d,V6)
#cumsum
V7<-cumsum(d$V6)
d<-cbind(d,V7)
#export variable into list
var_t<-paste(variab[i],"_v", sep="")
#### ПРОБЛЕМЫ НЕТ :)
mylist = c(mylist,data.frame(d$V7))
names(mylist)[i] = var_t
}
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 18:57
gamm
Анна писал(а):нет, нет! у меня именно что пустой лист, куда я в цикле хочу добавлять колонки с данными, и проблема в том, что названия этих колонок у меня идут из переменных. можно как то с листом справиться?
лист у меня от того, что cumsum разной длины и поэтому датафрейм не получится
1) по русски "лист" зовут списком
2) это не колонки. Забудьте Ёксел, он до добра не доведет. Это вектора, являющиеся элементами именованного списка.
3)
p.names<-c("A","B","C")
p.len<-c(3,7,2)
p.list<-list()
for(i in 1:length(p.names)) {
p.list[[p.names
]]<-rnorm(p.len)
}
p.list$A
[1] 1.2483060 0.3954658 -0.7471435
p.list[["A"]]
[1] 1.2483060 0.3954658 -0.7471435
p.list[[1]]
[1] 1.2483060 0.3954658 -0.7471435
p.list
$A
[1] 1.2483060 0.3954658 -0.7471435
$B
[1] -0.09112313 -0.49859972 0.41917197 0.98078393 -1.43580953 -1.02788373 -0.50509998
$C
[1] 0.4321653 -1.0340990
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 20:10
Анна
спасибо огромное Максим и gamm!!!
c вашей помощью удалось мне написать нужную функцию. Я поясню цель, чтобы было понятно зачем мне нужны такие операции хитрые с именами - может быть покритикуете мой подход и алгоритм? буду очень благодарна
Есть у меня N-папок. В каждой папке по 19 csv файлов (в каждом 4 столбца, список файлов у меня назван variab).
Мне нужно пройтись по всем папкам и для каждой сделать отдельный список (list) в R
Список должен состоять из 38 векторов - по два вектора из каждого csv файла (там еще кое-какой расчет по колонкам - но это не так важно). При этом имена векторов списка должны соответствовать названиям csv файлов, а имя списка - должно соответствать имени папки.
То есть структура готового набора данных в результате такая:
species1.list
$temp_v
$temp_n
$prec_v
$prec_n
species2.list
$temp_v
$temp_n
$prec_v
$prec_n
species3.list
$temp_v
$temp_n
$prec_v
$prec_n
вот мой код (он небольшой, просто с комментариями вышел длинным). Попробую его еще переписать по алгоритму который предложил gamm - то есть сначала сделать вектор имен для списка, и сразу присваивать в момент расчета. Но может быть заметите еще какие-то проблемы\ньюансы?
во вложении - тестовый набор данных со скриптом
Код: Выделить всё
# function to import csv files, calculate additional weights and cumsum and combine into lists
readcsv<-function(varlist, specieslist){
species<-read.table("species.lst",header=FALSE)
species$V1 <- as.character(species$V1)
variab<-read.table("var.lst",header=FALSE)
variab$V1 <- as.character(variab$V1)
for (i in 1:nrow(species)){
data_list = list()
name_list = list()
for (j in 1:nrow(variab)) {
#import $species$var.csv
afile<-paste(species$V1[i],variab$V1[j],".csv",sep="")
adata<-read.csv(paste(species$V1[i],"\\",afile,sep=""),header=FALSE)
#calculate column weight - percentage of cells occupied by particular value
V5<-unlist(lapply(adata$V2, function(x) (100*x)/sum(adata$V2)))
adata<-cbind(adata,V5)
#normalized values
V6<-(adata$V4/adata$V5)
adata<-cbind(adata,V6)
#cumsum
V7<-cumsum(adata$V6)
adata<-cbind(adata,V7)
#export variable into list
var_t<-paste(variab$V1[j],"_v", sep="")
data_list = c(data_list,data.frame(adata$V7))
names(data_list)[j] = var_t
#export variable code into list
var_tn<-paste(variab$V1[j],"_n", sep="")
name_list = c(name_list,data.frame(adata$V2))
names(name_list)[j] = var_tn
}
#get species name
unique_list_name<-paste(species$V1[i],"_out", sep="")
#create temporal combined list
tmp<-append(data_list,name_list)
#assign data to the unique name
assign(unique_list_name,tmp)
#remove all temporal values
rm(data_list)
rm(name_list)
rm(tmp)
rm(unique_list_name)
}
}
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 20:21
Максим Дубинин
так работает? если работает - ну и отлично
нюансов много разных, их замучаешься все поднимать, например scan лучше в данном случае изящнее, чем read.table, я это правил.
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 20:26
Анна
спасибо Максим - если честно, если бы не ты - точно не смогла бы разобраться. А почему scan лучше?
Re: передать переменную, а не character
Добавлено: 02 ноя 2010, 22:27
gamm
Анна писал(а):
c вашей помощью удалось мне написать нужную функцию. Я поясню цель, чтобы было понятно зачем мне нужны такие операции хитрые с именами - может быть покритикуете мой подход и алгоритм? буду очень благодарна
непонятно, зачем все эти сложности. Кто мешает пройтись по всем папкам, и сделать ОДНУ таблицу, в которой будет идентификация, откуда что взяли: в первом столбце (назовем его ID_older) - имя папки, во втором (назовем его ID_csv) - имя csv файла, в остальных данные.
R позволяет полностью имитировать SQL для выборки и агрегации данных, поэтому можно спокойно породить индекс:
cur.ind<-(my.table$ID_folder =="AAA") & (my.table$ID_csv =="BBB")
cur.data<-my.table[cur.ind,]
Re: передать переменную, а не character
Добавлено: 03 ноя 2010, 00:55
Максим Дубинин
Анна, еще, можно просто сделать список списков или общий список и не надо плясок с созданием переменных рантайм, имхо это странно. А обращаться по индексам, ведь порядок вхождения видов тебе известен.
Код: Выделить всё
>new = list(name_list,data_list)
> str(new)
List of 2
$ :List of 2
..$ alt_n : int [1:2660] 3 3 8 22 28 39 42 38 60 42 ...
..$ tave_10_n: int [1:178] 1 1 1 1 1 5 1 2 4 2 ...
$ :List of 2
..$ alt_v : num [1:2660] 0.389 0.747 1.168 1.579 2.002 ...
..$ tave_10_v: num [1:178] 0 0 0 0 0 ...
или
Код: Выделить всё
> new = append(name_list,data_list)
> str(new)
List of 4
$ alt_n : int [1:2660] 3 3 8 22 28 39 42 38 60 42 ...
$ tave_10_n: int [1:178] 1 1 1 1 1 5 1 2 4 2 ...
$ alt_v : num [1:2660] 0.389 0.747 1.168 1.579 2.002 ...
$ tave_10_v: num [1:178] 0 0 0 0 0 ...
Re: передать переменную, а не character
Добавлено: 03 ноя 2010, 07:57
gamm
Анна писал(а):бьюсь второй день c R и не могу элементарную вещь сделать. Как в R сделать так, чтобы он воспринимал слово как переменную, а не как character?
name <- "index1"
mylist$name <- c(1:10)
вот так он думает что name - это слово такое, а можно ли как сделать так, чтобы он считывал значение переменной и его вставлял? чтобы в результате было
возвращаясь к исходному сообщению. ... уж если именно так хочется, то и это можно, благо R - интерпретатор:
name <- "index1"
mylist<-list()
(tmp.A<-sprintf("mylist$%s <- c(1:10)",name)) # получаем символьную строку программы
[1] "mylist$index1 <- c(1:10)"
(tmp.B<-parse(text=tmp.A)) # парсим ее, превращая в выражение (код программы)
expression(mylist$index1 <- c(1:10))
attr(,"srcfile")
<text>
eval(tmp.B) # выполняем код программы
print(mylist) # наслаждаемся результатом
$index1
[1] 1 2 3 4 5 6 7 8 9 10
это позволяет вообще написать программу, которая пишет программу, которая ... а потом все это выполнить (в доме, который построил Джек).
Но у меня сложилось впечатление, что для Вашей задачи (задача нам неизвестна) та конструкция, которую Вы громоздите, не нужна, и даже вредна - снижается унификация алгоритма, он становится зависимым от данных.