передать переменную, а не character

Вопросы по статистическому пакету R. Не обязательно гео.
Ответить
Анна
Завсегдатай
Сообщения: 386
Зарегистрирован: 07 фев 2004, 14:31
Репутация: 7
Откуда: Лозанна
Контактная информация:

передать переменную, а не character

Сообщение Анна »

бьюсь второй день 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
		
		
	}
	
}
ferganaalt.csv
данные для тестирования
(58.01 КБ) 727 скачиваний
species.txt
(15 байт) 574 скачивания
var.txt
(12 байт) 665 скачиваний
Аватара пользователя
Максим Дубинин
MindingMyOwnBusiness
Сообщения: 9129
Зарегистрирован: 06 окт 2003, 20:20
Репутация: 748
Ваше звание: NextGIS
Откуда: Москва
Контактная информация:

Re: передать переменную, а не character

Сообщение Максим Дубинин »

Есть пара способов, прости я не стал смотреть в сам скрипт и данные, скажи если что-то непонятно, я могу глянуть более подробно:

Первый

Код: Выделить всё

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]
пристегивайтесь, турбулентность прямо по курсу
Анна
Завсегдатай
Сообщения: 386
Зарегистрирован: 07 фев 2004, 14:31
Репутация: 7
Откуда: Лозанна
Контактная информация:

Re: передать переменную, а не character

Сообщение Анна »

спасибо!
а как сделать так, чтобы именно имя присваивалось из переменной?

Код: Выделить всё

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
Аватара пользователя
Максим Дубинин
MindingMyOwnBusiness
Сообщения: 9129
Зарегистрирован: 06 окт 2003, 20:20
Репутация: 748
Ваше звание: NextGIS
Откуда: Москва
Контактная информация:

Re: передать переменную, а не character

Сообщение Максим Дубинин »

хм, то что ты называешь листом это фрейм данных, лист - совсем другая структура в 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]
пристегивайтесь, турбулентность прямо по курсу
Анна
Завсегдатай
Сообщения: 386
Зарегистрирован: 07 фев 2004, 14:31
Репутация: 7
Откуда: Лозанна
Контактная информация:

Re: передать переменную, а не character

Сообщение Анна »

нет, нет! у меня именно что пустой лист, куда я в цикле хочу добавлять колонки с данными, и проблема в том, что названия этих колонок у меня идут из переменных. можно как то с листом справиться?
лист у меня от того, что cumsum разной длины и поэтому датафрейм не получится
Аватара пользователя
Максим Дубинин
MindingMyOwnBusiness
Сообщения: 9129
Зарегистрирован: 06 окт 2003, 20:20
Репутация: 748
Ваше звание: NextGIS
Откуда: Москва
Контактная информация:

Re: передать переменную, а не character

Сообщение Максим Дубинин »

Пардоньте :) Переделка под листы:

Код: Выделить всё

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
}
пристегивайтесь, турбулентность прямо по курсу
gamm
Гуру
Сообщения: 4168
Зарегистрирован: 15 окт 2010, 08:33
Репутация: 1107
Ваше звание: программист
Откуда: Казань

Re: передать переменную, а не character

Сообщение 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
Анна
Завсегдатай
Сообщения: 386
Зарегистрирован: 07 фев 2004, 14:31
Репутация: 7
Откуда: Лозанна
Контактная информация:

Re: передать переменную, а не character

Сообщение Анна »

спасибо огромное Максим и 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)
	
	}

}
Вложения
test.rar
тестовый набор
(31.32 КБ) 482 скачивания
Последний раз редактировалось Анна 02 ноя 2010, 20:34, всего редактировалось 3 раза.
Аватара пользователя
Максим Дубинин
MindingMyOwnBusiness
Сообщения: 9129
Зарегистрирован: 06 окт 2003, 20:20
Репутация: 748
Ваше звание: NextGIS
Откуда: Москва
Контактная информация:

Re: передать переменную, а не character

Сообщение Максим Дубинин »

так работает? если работает - ну и отлично

нюансов много разных, их замучаешься все поднимать, например scan лучше в данном случае изящнее, чем read.table, я это правил.
пристегивайтесь, турбулентность прямо по курсу
Анна
Завсегдатай
Сообщения: 386
Зарегистрирован: 07 фев 2004, 14:31
Репутация: 7
Откуда: Лозанна
Контактная информация:

Re: передать переменную, а не character

Сообщение Анна »

спасибо Максим - если честно, если бы не ты - точно не смогла бы разобраться. А почему scan лучше?
gamm
Гуру
Сообщения: 4168
Зарегистрирован: 15 окт 2010, 08:33
Репутация: 1107
Ваше звание: программист
Откуда: Казань

Re: передать переменную, а не character

Сообщение 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,]
Аватара пользователя
Максим Дубинин
MindingMyOwnBusiness
Сообщения: 9129
Зарегистрирован: 06 окт 2003, 20:20
Репутация: 748
Ваше звание: NextGIS
Откуда: Москва
Контактная информация:

Re: передать переменную, а не character

Сообщение Максим Дубинин »

Анна, еще, можно просто сделать список списков или общий список и не надо плясок с созданием переменных рантайм, имхо это странно. А обращаться по индексам, ведь порядок вхождения видов тебе известен.

Код: Выделить всё

>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 ...
пристегивайтесь, турбулентность прямо по курсу
gamm
Гуру
Сообщения: 4168
Зарегистрирован: 15 окт 2010, 08:33
Репутация: 1107
Ваше звание: программист
Откуда: Казань

Re: передать переменную, а не character

Сообщение 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


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

Но у меня сложилось впечатление, что для Вашей задачи (задача нам неизвестна) та конструкция, которую Вы громоздите, не нужна, и даже вредна - снижается унификация алгоритма, он становится зависимым от данных.
Ответить

Вернуться в «R»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя