Search code examples
pythonarrayslistnumpymultiplication

Multiplying arrays with alternating column selection


I have got a file testforce.dat that shows values divided in 9 columns and 3 rows. The first 3 column represents:

p1   p2  p3 f1  f2   f3 r1  r2  r3    
18   5  27  20  21   8  14  12  25
 9  26  23   1   4  10   7  16  24
19  22  15  13  17   6  11   2   3

I have got 100 files of this fashion.
I now want to calculate for the file force_00000.dat the vector g = [sum(p1*f1), sum(p2*f2), sum(p3*f3)] but for the next file force_00001.dat the vector should use other columns h = [sum(p1*r1), sum(p2*r2), sum(p3*r3)].

At the moment I am using the glob function to read my files into arrays. It puts every row into one array. I am not sure how to get my alternating array multiplication done and would appreciate any suggestions :)

import numpy as np
import glob

i = 100
for x in range(0,int(i)):


## turns x into a string and adds if necessary "0" to achieve a fixed digit number; 
y = str(x).zfill(5) 

## the structure of the forcefile is "force_[00000-00099]";
files = sorted(glob.glob('.//results/force/force_%s.dat' % y))  
column_names=('#position')


print files

## loads the file data into arrays 
arrays=[np.loadtxt(filename) for filename in files]
print arrays

Edit: I tested the load of the first file with:

b=np.array(arrays)
print b.shape

And I get (1,3,9) for the shape of my generated array.

Edit2: I had the idea to use "usecols" and then multiply the desired values:

xposition=[np.loadtxt(filename,usecols= (0,1,2)) for filename in files]
xforce1=[np.loadtxt(filename,usecols= (3,4,5)) for filename in files]
print xposition
print xforce1
xp=np.asarray(xposition)
xf1=np.asarray(xforce1)

print xp
g=np.multiply(xp,xf1)
print g

this generated the following output:

[[[ 360.  105.  216.]
[   9.  104.  230.]
[ 247.  374.   90.]]]

which means I have (p11 and f11 being the values of the first row, p21 from second row...)

[[[p11*f11  p12*f12  p13*f13] 
 [p21*f21  p22*f22  p23*f23]
 [p31*f31  p32*f32   p33*f33]]]

which seems like I am slmost done for atleast one file. The desired g(g1,g2,g3) should look like:

p11*f11+p21*f21+p31*f31= g1
p12*f12+p22*f22+p32*f32= g2
p13*f13+p23*f23+p33*f33= g3

Sorry if that is a totally newbie question but I am not so familliar with python yet :)

For the issue with the alternating values I was thinking about using an if function that checks if "i" in the loop is an even number


Solution

  • loadtxt returns an array. [loadtxt(name) for name in filenames] produces a list of arrays, one array per name. np.array([...]) produces an array from that list. If the individual arrays are all the same size, the resulting array will be 3d.

    If you need to treat every other file differently you could access them as a set with indexing

    arr[::2,...] 
    arr[1;:2,...]
    

    To multiply the 2 sets of columns from your example file:

    In [558]: txt=b"""p1   p2  p3 f1  f2   f3 r1  r2  r3    
         ...: 18   5  27  20  21   8  14  12  25
         ...:  9  26  23   1   4  10   7  16  24
         ...: 19  22  15  13  17   6  11   2   3"""
    
    In [560]: arr = np.loadtxt(txt.splitlines(),skiprows=1,dtype=int)
    In [561]: arr
    Out[561]: 
    array([[18,  5, 27, 20, 21,  8, 14, 12, 25],
           [ 9, 26, 23,  1,  4, 10,  7, 16, 24],
           [19, 22, 15, 13, 17,  6, 11,  2,  3]])
    
    In [562]: arr[:, 0:3]*arr[:, 3:6]
    Out[562]: 
    array([[360, 105, 216],
           [  9, 104, 230],
           [247, 374,  90]])
    
    In [563]: arr[:, 0:3]*arr[:, 6:9]
    Out[563]: 
    array([[252,  60, 675],
           [ 63, 416, 552],
           [209,  44,  45]])
    

    If arr was a 3d array from load multiple files,

    arr1 = arr[::2,...]
    arr2 = arr[1::2,...]
    arr1[:,:,0:3] * arr1[:,:,3:6]
    etc