I'm trying to use the table extension for my model. My code includes the table:from-list command to generate the table. However I am getting an error saying **"Extension exception: expected a two-element list". I generate the list from a txt file that is two columns of numerical data. Apparently this is not the correct format to create a two-element list, but I can't find any documentation describing the appropriate format. How can a two-element list be generated?
Also, is it possible to build a table with more than two elements? Time is serving as the key in my table, but I would like to build a table such that this key would update three different variables (hence a four column table: ticks variable1 variable2 variable3)
Any good resources for learning my way around the tables and arrays extensions is also welcomed (I've already checked out the extensions guide but don't have the hang of it yet).
extensions [table]
Globals
[
list-O2
table-O2
]
to setup
make-lsolutes ; loads lists for solute data (based on node 96)
make-tsolutes
to go
if table:has-key? table-O2 ticks
[ update-from-FEM]
tick
end
to make-lsolutes
ifelse ( file-exists? "96O214day.txt" )
[
set list-O2 []
file-open "96O214day.txt"
while [ not file-at-end? ] [set list-O2 lput file-read list-O2]
file-close
]
[ user-message "There is no 96O214day.txt file in current directory!" ]
end
to make-tsolutes
set table-O2 table:from-list list-O2
end
to update-from-FEM
ask insulation
[ set O2 table:get table-O2 ticks]
end
The txt files to make the solute lists have two columns. Left column is time, and the right column is O2 concentration. Columns are separated by spaces.
A two-element list would look like this:
[[key1 val1][key2 val2][keyn valn]]
I would use the file-open, file-read-line, and while [not file-at-end?] primitives to iterate over your input and use the String primitives to create the pair-lists from your input file. Something like:
let the-list []
file-open filename.txt
while [not file-at-end?][
let input file-read-line
;; find the start and end position/index of key and value (X,Y,O,P) using the position primitive on your delimiter
let key substring input X Y
let value substring input O P
let the-pair (list key value)
set the-list lput the-pair the-list
]
You can embed tables inside tables. So if you want several values as key value, just create a table for each entry and put them in your main table.
Related
I have a question about using the csv extension in NetLogo. I would like to export a .csv file using the csv extension. However, my output is per tick and when using csv: to-file it only writes the last tick. It's like csv:to-file would delete previous ticks. I looked for ways not to delete and couldn't find a solution. Does anyone know if it is possible to use csv: to-file per tick, without erasing previous ticks? I need to use csv because I am working with lists. OBS.: It is not possible to accumulate the values generated at each iteration, because the list would be large and ended up having a memory problem
Thanks in advance
Below is a code showing that csv: to-file deletes the previous information (only the values 5,6 and 7,8 appear in the file)
to test
csv:to-file (" test-1.csv" ) [ [1 2] [ 3 4 ] ]
csv:to-file (" test-1.csv" ) [ [5 6] [ 7 8 ] ]
end
yes, csv:to-file is for writing a whole file at a time. To write one line each tick, you need csv:to-row, which converts a list to a line of csv output:
file-open "The-file-name.csv"
file-print csv:to-row (list output-1 output-2 output-3 ...)
file-close
(This is quite fast and will not slow your code down unless your model is extremely simple. Unfortunately there is not an example of it in the Models Library's csv code example.)
I am trying to export a file in NetLogo 6.2. But I'm having 2 difficulties:
put only 1 header in the output. It only comes out with multiple headers or without header (see figures below)
multiple headers:
without header:
and I would like it to look like this (below). Is it possible?
close the file so that multiple results are not written to the same file. When I use the command "carefully" and "file-delete" and "[]" only the result of a turtle appears:
if I remove the commands "carefully" and "file-delete" and "[]" the result of all turtles appears. However, if I run the model several times, the results will be saved on top. How is it possible to close the file without changing the result?
The code:
globals [ outifile ]
turtles-own [ my-xcor my-ycor my-timer ]
to output
; carefully ;; using this command to close the file only saves the path of the last turtle
; [ file-delete ( word outfile name ".csv" ) ] ;; using this command to close the file only saves the path of the last turtle
; [ ] ;; using this command to close the file only saves the path of the last turtle
file-open ( word outifile ".csv" )
file-print ( word "id;my_xcor;my_ycor;my_timer" ) ;; when removing this line, there is no header
file-print ( word self " ; " my-xcor " ; " my-ycor " ; " my-timer )
file-close
end
The two issues have the same cause and same solution.
For point 1
This is because apparently to output is executed by every turtle, which means that every turtle will first print the headers and then print the values. Note that this is exactly what you're asking them to do, having both of the following lines of code being executed by each turtle:
file-print ( word "id;my_xcor;my_ycor;my_timer" )
file-print ( word self " ; " my-xcor " ; " my-ycor " ; " my-timer )
Therefore, you have to print the headers first, before asking turtles to do anything (i.e. the observer is the one who has to print the headers, and then has to ask turtles to print values).
For point 2
This issue too comes from the fact that you have every turtle executing the whole to output procedure. In this case, this means that every turtle will run
carefully
[file-delete (word outfile name ".csv")]
[]
Hence, every turtle will make sure that the file has been deleted (or that it doesn't exist) before writing their output.
Again, this is something that the observer should do, because it needs to be done only once.
Fix
To solve these things, you have two absolutely equivalent options:
Option 1
Leave to output a turtle-context procedure (i.e. a procedure executed by turtles) and place the observer's tasks somewhere else in your code, where you know that they will be executed only once - for example in setup or some equivalent place:
to setup
; Here you have your normal 'setup' code, plus:
prepare-output
end
to prepare-output
carefully
[file-delete (word outfile name ".csv")]
[]
file-open (word outifile ".csv")
file-print (word "id;my_xcor;my_ycor;my_timer")
file-close
end
So the observer will take care of cleaning the file and creating headers, and when turtles will run to output they will only need to print their values.
Option 2
Change to output from a procedure that is executed by turtles, to a procedure that is executed by the observer. In this case, at the beginning of the procedure the observer will do once its observer's things, and only then ask all turtles to print their values. Once the turtles are done, the observer closes the file. For example:
to go
; Here you have your normal 'go' code, plus something like:
if (stop-condition-reached?) [
output
stop
]
end
to output
carefully
[file-delete (word outfile name ".csv")]
[]
file-open (word outifile ".csv")
file-print (word "id;my_xcor;my_ycor;my_timer")
ask turtles [
file-print (word self " ; " my-xcor " ; " my-ycor " ; " my-timer)
]
file-close
end
The logic behind both options is exactly the same: the observer does its things once (deleting the old file and creating a new one with headers), then each turtle prints its values.
The difference between the two options is only in how the code is organised - i.e. is to output a procedure executed by turtles, or by the observer (who then asks turtles to print)?
In general it is important to keep track of who is executing what.
For this reason, in my code I always comment the declaration of each procedure with a note stating what context such procedure is being executed from (e.g. observer context, turtle context, patch context, link context).
I have a table with about 500 variables and 2000 cases. The type of these variables varies. My supervisor has asked me to produce a table listing all the numeric variables, along with their maximums and minimums. I am supposed to use SPSS because R apparently messes up the value labels.
I've only done very basic things in SPSS before this, like finding statistics for single variables, and I'm not sure how to do this. I think I should probably do something like:
*Create new table*
DATASET DECLARE maxAndMin.
*Loop through all variables: Use conditional statement to identify numeric variables*
DO REPEAT R=var1 TO varN.
FREQUENCIES VARIABLES /STATISTICS=MINIMUM
END REPEAT
*Find max and minimum*
I'm not sure how to go about this though. Any suggestions would be appreciated.
The following code will first make a list of all numeric variables in the dataset (and store it in a macro called !nums) and then it will run an analysis of those variables to tell you the mean, maximum and minimum of each:
SPSSINC SELECT VARIABLES MACRONAME="!nums" /PROPERTIES TYPE= NUMERIC.
DESCRIPTIVES !nums /STATISTICS=MEAN MIN MAX.
You can use the following code to create a tiny dataset to test the above code on:
data list list/n1 (f1) t1(a1) n2(f1) t2(a1).
begin data
1 "a" 34 "b"
2 "a" 23 "b"
3 "a" 52 "b"
4 "a" 71 "b"
end data.
If SUMMARIZE produces a nice enough table for you, here is a "non-extension" way of doing it.
file handle mydata /name="<whatever/wherever>".
data list free /x (f1) y (a5) z (F4.2).
begin data.
1 yes 45.67
2 no 32.00
3 maybe .
4 yes 22.02
5 no 12.79
end data.
oms select tables
/destination format=sav outfile=mydata
/if subtypes="Descriptive Statistics" /tag="x".
des var all.
omsend tag="x".
get file mydata.
summarize Var1 Mean Minimum Maximum /format list nocasenum nototal
/cells none /statistics none /title "Numeric Variables Only".
or use a DATASET command instead of file handle if you don't need the file on disk.
I am new to netlogo and I am having trouble understanding the performance issues related to using run with anonymous procedures.
My main concern is whether using run or runresult with an anonymous procedure incurs performance penalties or if this is something related to using run/runresult with string input only.
Thanks
Some code :
My understanding is that you can achieve the same result with the following two different ways (there might be more but like I said I'm just starting with netlogo so these are the ones I can come up with):
to-report list-made-up-of-empty-lists? [ a-list ]
let helper [ [ arg ] -> ( reduce and ( map empty? arg ) )]
report ( map helper ( list a-list ) )
end
vs
to-report list-made-up-of-empty-lists? [ a-list ]
let helper [ [ arg ] -> ( reduce and ( map empty? arg ) )]
report ( list ( runresult helper a-list ) )
end
What's the difference?
Also, in the documentation it is stated that something like runresult ( word "helper " a-list ) should work in principle but I can't make it run (I get runtime errors).
Shouldn't this last line evaluate correctly? What am I doing wrong? Also, in what sense can runresult 'run' strings?
Executing an anonymous procedure is significantly quicker than running a string. The issue is that the string needs to be converted to some executable code, then executed.
If you're comparing user defined functions vs anonymous procedures, that's a different story and dependent on use case. For example, if you have a for loop and create an anonymous function inside the loop, rather than creating it once outside the loop (or pre-defining it), you'd potentially start to see a slow down.
Netlogo's Run documentation:
run command
(run command input1 ...)
run string
runresult reporter
(runresult reporter input1 ...)
runresult string
The run form expects the name of a command, an anonymous command, or a string containing commands. This agent then runs them.
The runresult form expects the name of a reporter, an anonymous reporter, or a string containing a reporter. This agent runs it and reports the result.
Furthermore, the reason why your code won't work with a string is due to the following: Netlogo's string commands can't set/read local variables. Your helper is a local variable.
See the documentation:
Anonymous procedures may freely read and/or set local variables and
procedure inputs. Trying to do the same with strings may or may not
work and should not be relied on.
I want to use the system date to name my output files, I have created a variable to do that but I find it to be "unclean". How can I create a reporter procedure to create a variable that is just the current system date, say 18Feb2016, without removing items individually. Currently I am using
globals [
time
filename
]
to setup
ca
set time (remove-item 6(remove-item 7(remove-item 8 (remove "-"(remove " "(remove "."
(remove ":" date-and-time)))))))
set filename (word "test-" time ".csv"
if file-exists? filename
[file-close
file-delete filename
]
file-open filename
end
You could definitely reduce your code by using the substring primitive.
set date (remove "-" (substring date-and-time 16 27))
set time (remove "." remove ":" remove " " (substring date-and-time 0 15))
However, I don`t know if there is a more elegant way to access the system date and time in NetLogo without the need of string reconstruction.