[Tutor] Import tabular data file and assign to variables

Jeff Shannon jeff at ccvcorp.com
Thu Sep 16 20:16:34 CEST 2004


RenderPipe wrote:

> I was thinking of creating a dictionary object for each frame but I do
> not know how to extract the data in the colums and assing them to a
> dictionary.

That sounds like a pretty good plan.  If you want to get slightly more 
advanced, you could write a small class and then create an instance of 
that class for each line.  The big advantage here is that you can 
encapsulate a lot of the code to process each line into the class, and 
you can later add methods that do interesting things with your data. 
But for a simple approach, dictionaries (or even tuples) will work well.

> Here's what i have come up with so far:
> 
> import string

You're not actually using the string module here, so you can skip the 
import.

> myfile = open("MyFile")
> data = myfile.readlines()
> for line in data:
>         rs  = line.split("\t")
>         print rs

If you call split() with no arguments, then it will default to 
splitting on all whitespace.  If there's multiple whitespace 
characters together, this default mode will treat them as one.  So, 
for example, when I do this on one of your sample lines, I get this:

 >>> x
'    -31.5227      7.7864    -74.4018     -2.4335     -8.7991\r\n'
 >>> x.split()
['-31.5227', '7.7864', '-74.4018', '-2.4335', '-8.7991']
 >>>

Note that this has also eliminated the extra \r\n characters at the 
end.  However, there's a slight catch here -- these are still strings, 
not floating-point numbers.  You'll need to convert them, which we can 
do to the whole list easily with a list comprehension:

 >>> x
'    -31.5227      7.7864    -74.4018     -2.4335     -8.7991\r\n'
 >>> rs = [float(num) for num in x.split()]
 >>> rs
[-31.5227, 7.7864000000000004, -74.401799999999994, -2.4335, 
-8.7990999999999993]
 >>>

(The numbers aren't displaying exactly, because there's tiny 
representation errors when switching between decimal fractions and 
binary fractions.  It's normal, and shouldn't be a problem unless you 
need *very* exact precision.)

With that, you should be able to put your data into a dictionary or a 
class pretty easily.  Just as an example of how convenient using a 
class can be, look at this:

 >>> class Pos3D:
... 	def __init__(self, transx, transy, transz, rotx, roty):
... 		self.transx = transx
... 		self.transy = transy
... 		self.transz = transz
... 		self.rotx = rotx
... 		self.roty = roty
... 		
 >>> instance = Pos3D(*rs)
 >>> instance
<__main__.Pos3D instance at 0x02C9EA00>
 >>> instance.transx, instance.transy, instance.transz
(-31.5227, 7.7864000000000004, -74.401799999999994)
 >>> instance.rotx, instance.roty
(-2.4335, -8.7990999999999993)
 >>>

Because the Pos3D class knows what order to expect data in, I can 
simply tell Python to expand the list of data into a normal argument 
list for __init__() -- that's what the * in Pos3D(*rs) means.  Now I 
can conveniently refer to all of this data with simple dotted-name 
syntax.  I could also easily write methods like gettrans(), which 
would return (transx, transy, transz), and getrot(), which would 
return (rotx, roty), making further work with the data that much simpler.

Hope that this helps.

Jeff Shannon
Technician/Programmer
Credit International




More information about the Tutor mailing list