Please Consider :
Needs["ErrorBarPlots`"];
fixNumberF1F6 = {{{7.11`, 7.51`, 11.14`, 8.19`, 6.58`},
{2.14`, 2.33`,2.25`, 1.53`,1.71`}},
{{4.69`, 4.79`, 3.78,4.34`, 4.8`},
{2.22`, 2.71`, 3.18`, 2.29`, 1.93`}}}
fixNumberF1F6[[1,1]] refers to the mean fixation number for each subject for condition 1,
fixNumberF1F6[[1,2]] the standard Deviation of those means.
fixNumberF1F6[[2]] refers to condition 2.
plotOptionsXX[title_, yName_, xName_, colors_: Black] :=
{Frame -> {{True, False}, {True, False}},
PlotStyle -> colors,
PlotLabel ->
Style[title, Bold, 14, Opacity[1], FontFamily -> "Helvetica"],
PlotStyle -> Directive[Black, PointSize[Medium]],
PlotRangePadding -> 0,
Frame -> {{True, False}, {True, False}},
LabelStyle -> Directive[Black, Bold, 12],
FrameLabel -> {{Style[yName, Opacity[1]],
None}, {Style[xName, Opacity[1]], None}},
FrameStyle -> Opacity[0],
FrameTicksStyle -> Opacity[1],
AxesStyle -> Directive[Black, 12],
ImageSize -> laTaille};
ErrorListPlot[fixNumberF1F6[[#]] // Transpose,
PlotRange -> {{0, 6}, {0, 15}},
ImageSize -> 300,
FrameTicks ->{{Range[1, 13, 2], None},{{1, 2, 3, 4, 5}, None}},
PlotStyle -> Directive[Black, AbsolutePointSize[10], AbsoluteThickness[2]],
plotOptionsXX["Mean Fixation number", "Fixation Nuber", "SubNo"]] & /# Range[2]
The Plot On the Left represent each subject average fixation number along with the standard deviation for condition 1. On the right for condition 2.
How could I plot them both on 1 plot ?
If this :
fixNumberF1F6across = {{8.10, 1.99}, {4.48, 2.46}}
was the mean and SD across subject, How could I show both ?
-How can I show 2 conditions on a similar plot for different subjects
-How could I show the group mean and SD on it to.
Edit:
I started from over. Given how the data are simple and clean, it may be easiest to use ListPlot and
add the bars via an Epilog.
You can still tweak it a bit--e.g. put a slight space between the blue and red data points and bars, add a legend, etc, but the basic idea is there.
data = {{{7.11`, 7.51`, 11.14`, 8.19`, 6.58`}, {2.14`, 2.33`, 2.25`, 1.53`, 1.71`}}, {{4.69`, 4.79`, 3.78, 4.34`, 4.8`}, {2.22`, 2.71`, 3.18`, 2.29`, 1.93`}}};
ListPlot[{data[[1, 1]], data[[2, 1]]},
PlotStyle -> {{PointSize[.025], Red}, {PointSize[0.025], Blue}},
Frame -> True,
PlotRange -> {{0.5, 5.5}, {0, 14}},
FrameTicks -> {{Automatic, Automatic}, {Range[5], None}},
FrameLabel -> {{"Fixation (ms)", None}, {"Subject", None}},
Epilog -> {{Red, Thickness[0.003], Dashed,
Line[{{0, m1 = Mean#data[[1, 1]]}, {5.5, m1}}],
Blue, Line[{{0, m1 = Mean#data[[2, 1]]}, {5.5, m1}}]},
Thickness[0.005], Red,
Line[{{#[[1]], #[[2, 1]]}, {#[[1]], #[[2, 2]]}}] & /#
Transpose#{Range[5], ({#[[1]] + #[[2]], #[[1]] - #[[2]]} & /#
Transpose#data[[1]])},
Thickness[0.005], Blue,
Line[{{#[[1]], #[[2, 1]]}, {#[[1]], #[[2, 2]]}}] & /#
Transpose#{Range[5], ({#[[1]] + #[[2]], #[[1]] - #[[2]]} & /#
Transpose#data[[2]])},
}]
The BoxWhiskerChart below is from your data. If this looks vaguely like something you are interested in, it could be modified so that the spread from the 25th percentile to the 75% percentile is altered to reflect the spread of one s.d. above and below the mean.
And, yes, it is easy to overlay the group means (N=5) onto the Chart.
[The reason there isn't perfect symmetry around the mean is that I used your means and standard deviations to generate raw data, assuming a normal distribution. I only used 100 data points per trial, so a little skewing is natural. This would not happen if we were to tweak the chart to reflect standard deviations, which are symmetrical.]
For any number of series:
plotseries[a_] :=
Module [{col = ColorData[22, "ColorList"]},
Plot[Evaluate#(Piecewise[{#[[2]], #[[1]] - 1/3 <= x <= #[[1]] + 1/3} & /#
Thread[List[Range#Length##, #]]] & /#
({a[[#, 1]] + a[[#, 2]], a[[#, 1]] - a[[#, 2]]}) & /#
(Range#Length#a)), {x, 0, 1 + Length#(a[[1, 1]])},
ClippingStyle -> None,
PlotStyle -> {None},
Exclusions -> False,
Filling -> ({2 # - 1 -> {{2 #}, Directive[col[[#]], Opacity[.2]]}} & /#
Range#Length#a),
Ticks -> {Range#Length[a[[1, 1]]], Range##2 &},
AxesLabel -> {Style["Subject", Medium, Bold], Style["Fixation Time", Medium, Bold]},
Epilog ->
MapIndexed[{Directive[col[[#2[[1]]]], PointSize[.03]],
Point#Thread[List[Range#Length[#1[[1]]], #1[[1]]]]} &, a]
]
]
b = Table[{Table[j^(i/3) + i, {j, 6}], Table[1, {j, 6}]}, {i, 1, 3}];
plotseries[b]
I don't work very much with error plots, so this might very well be a non-standard form of displaying the data and hastily put together based on the example in the documentation for ErrorBarFunction.
(*split it up so it's easier to follow*)
meanCond1 = fixNumberF1F6[[1, 1]];
stdCond1 = fixNumberF1F6[[1, 2]];
meanCond2 = fixNumberF1F6[[2, 1]];
stdCond2 = fixNumberF1F6[[2, 2]];
x1 = Transpose#{meanCond1, meanCond2};
x2 = ErrorBar ### Transpose#{stdCond1, stdCond2};
Show#(ErrorListPlot[{#1},
ErrorBarFunction ->
Function[{coords, errs}, {Opacity[0.2], EdgeForm[{#2}],
Rectangle[coords + {errs[[1, 1]], errs[[2, 1]]},
coords + {errs[[1, 2]], errs[[2, 2]]}]}], PlotStyle -> #2,
Axes -> False, Frame -> True,
FrameLabel -> {"Condition 1", "Condition 2"}] & ###
Transpose#{Transpose#{x1, x2}, {Blue, Yellow, Green, Gray, Red}})
Each dot is a different subject. The x coordinate is the mean for condition 1 and the y coordinate is the mean for condition 2. The lengths of the sides of the rectangles are the respective standard deviations. So while it does overlap, if you're prudent in choosing colors (and if there aren't too many subjects), it could perhaps work.
ErrorListPlot[Transpose /# fixNumberF1F6,
PlotRange -> {{0, 6}, {0, 15}}, ImageSize -> 300,
FrameTicks -> {{Range[1, 13, 2], None}, {{1, 2, 3, 4, 5}, None}},
PlotStyle ->
{
Directive[Opacity[0.6],Black, AbsolutePointSize[10], AbsoluteThickness[2]],
Directive[Opacity[0.6],Gray, AbsolutePointSize[10], AbsoluteThickness[2]]
},
plotOptionsXX["Mean Fixation number", "Fixation Number", "SubNo"]
]
ErrorListPlot[fixNumberF1F6across, PlotRange -> {{0, 3}, {0, 15}},
ImageSize -> 300,
FrameTicks -> {{Range[1, 13, 2], None}, {{1, 2}, None}},
PlotStyle -> Directive[Black, AbsolutePointSize[10], AbsoluteThickness[2]],
plotOptionsXX["Mean Fixation number", "Fixation Number", "Condition Number"]
]
As to the 3rd. I don't see how you can talk about group means if you want to show the data of the individual subjects. The 4th (5th?) question is totally unclear. I suggest you remove those questions as they don't seem to be specific to Mathematica programming.
Related
I am trying to optimize a funciton that is trying to maximize the correlation between two (pandas) time series arrays (X and Y). This is done by using three parameters (a, b, c) and a third time series array (Z). The Z array is used to reindex the values in the X array (based on the parameters a, b, c) in such a way as to maximize the correlation of the reindexed X array (Xnew) with the Y array.
Below is some pseudo-code to demonstrate what I amy trying to do. I have attempted this using LMfit and scipy optimize but I am not sure how to make this task work in those packages. For example in LMfit if I tried to minimize the MyOpt function (which passes back a single value of the correlation metric) then it complains that I have more parameters than outputs. However, if I pass back the time series of the corrlation metric (diff) the the parameter values remain fixed at their input values.
I know the reindexing function I am using works because using the rather crude methods similar to the code below give signifianct changes in the mean (diff) metric passed back.
My knowledge of these optimizaiton packages is not up to scratch for this job so if anyone has a suggestion on how to tackle this, I would be greatfull.
def GetNewIndex(Z, a, b ,c):
old_index = np.arange(0, len(Z))
index_adj = some_func(a,b,c)
new_index = old_index + index_adj
max_old = np.max(old_index)
new_index[new_index > max_old] = max_old
new_index[new_index < 0] = 0
return new_index
def MyOpt(params, X, Y ,Z):
a = params['A']
b = params['B']
c = params['C']
# estimate lag (in samples) based on ambient RH
new_index = GetNewIndex(Z, a, b, c)
# assign old values to new locations and convert back to pandas series
Xnew = np.take(X.values, new_index)
Xnew = pd.Series(Xnew, index=X.index)
cc = Y.rolling(1201, center=True).corr(Xnew)
cc = cc.interpolate(limit_direction='both', limit_area=None)
diff = 1-np.abs(cc)
return np.mean(diff)
#==================================================
X = some long pandas time series data
Y = some long pandas time series data
Z = some long pandas time series data
As = [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2]
Bs = [0, 0 ,0, 1, 1, 1, 0, 0, 0, 1, 1, 1]
Cs = [5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6]
outs = []
for A, B, C in zip(As, Bs, Cs):
params={'A':A, 'B':B, 'C':C}
out = MyOpt(params, X, Y, Z)
outs.append(out)
I have recently started to use Plotly to make 3D plots in python and I wanted to create an animation of what is going on in terms of column vectos of a 3 by 3 matrix when applying Gaussain elimination.
I wrote a function to get the row echelon form and the history of the matrix obtained at each step.
Then I wanted to plot the comuns vectors at each step of the algorithm.
At first I was able to get an animation of the the evolution of the three vectors by adpating this code : https://plotly.com/python/visualizing-mri-volume-slices/
But then I wanted to show on each frame the three row vectors of a given step and the three row vectors from the matrix of the previous step with opacity 0.2.
And when I added that part of the code I got a strange behavior from Plotly. It only showed me the three first vectors which are given to the frame and not all of them.
Here the code I have so far :
import numpy as np
import numpy.linalg as la
import plotly.graph_objects as go
v1 = np.array([5,2,1])
v2 = np.array([2,3,2])
v3 = np.array([3,-1,1])
A = np.transpose(np.vstack([v1,v2,v3]))
# G, H = pivot_Gauss(A)
H = [np.array([[ 5, 2, 3],[ 2, 3, -1],[ 1, 2, 1]]), np.array([[ 1, 0, 0],[ 2, 3, -1],[ 1, 2, 1]]),
np.array([[ 1, 0, 0],[ 0, 3, -1],[ 1, 2, 1]]), np.array([[ 1, 0, 0],[ 0, 3, -1],[ 0, 2, 1]]),
np.array([[1, 0, 0],[0, 1, 0],[0, 2, 1]]), np.array([[1, 0, 0],[0, 1, 0],[0, 0, 1]]),
np.array([[1, 0, 0],[0, 1, 0],[0, 0, 1]]) ]
G = np.array([[1,0,0],[0,1,0],[0,0,1]]) # results obtained using the function pivot_Gauss(A)
nb_frames = len(H)
frames = []
v_norm = 5
colors = ["blue","red","green"]
for k in range(nb_frames): # go.Frame(data,name=str(k))
dat = []
for j in range(np.shape(A)[1]):
v = H[k][:,j]
if la.norm(v) != 0 :
d1 = go.Scatter3d( x=[0,v[0]],y=[0,v[1]],z=[0,v[2]],name="v"+str(k+j+1),hoverinfo='name',
marker=dict(size=0), line=dict(color=colors[j], width=10 ))
dat.append(d1)
d2 = go.Cone(x=[v[0]],y=[v[1]],z=[v[2]],
u=[v[0]/v_norm],v=[v[1]/v_norm],w=[v[2]/v_norm],sizeref=1,
sizemode="scaled",anchor="cm",name="v"+str(k+j+1),hoverinfo='x+y+z+name',
colorscale=[[0, colors[j]], [1,colors[j]]],showscale=False)
dat.append(d2)
if k>0 : # add column vectors of previous Gaussain elimination step (causes some troubles,
#if this if section is commented I get an animation of the three clumn vectors of current step)
vk = H[k-1][:,j]
if la.norm(v) != 0 :
d3 = go.Scatter3d( x=[0,vk[0]],y=[0,vk[1]],z=[0,vk[2]],name="v"+str(k+j+1),hoverinfo='name',
marker=dict(size=0), line=dict(color=colors[j], width=10), opacity = 0.2 )
dat.append(d3)
d4 = go.Cone(x=[vk[0]],y=[vk[1]],z=[vk[2]],
u=[vk[0]/v_norm],v=[vk[1]/v_norm],w=[vk[2]/v_norm],sizeref=1,
sizemode="scaled",anchor="cm",name="v"+str(k+j+1),hoverinfo='x+y+z+name',
colorscale=[[0, colors[j]], [1,colors[j]]],showscale=False,opacity=0.2)
dat.append(d4)
frames.append(go.Frame(data=dat,name=str(k)))
fig = go.Figure(frames=frames)
# Add data to be displayed before animation starts
for j in range(A.shape[1]):
v = A[:,j]
if la.norm(v) != 0 :
fig.add_trace( go.Scatter3d( x=[0,v[0]],y=[0,v[1]],z=[0,v[2]],name="v"+str(k+1),hoverinfo='name',
marker=dict(size=0), line=dict(color=colors[j], width=10 )) )
fig.add_trace( go.Cone(x=[v[0]],y=[v[1]],z=[v[2]],
u=[v[0]/v_norm],v=[v[1]/v_norm],w=[v[2]/v_norm],sizeref=1,
sizemode="scaled",anchor="cm",name="v"+str(k+1),hoverinfo='x+y+z+name',
colorscale=[[0, colors[j]], [1,colors[j]]],showscale=False) )
### This remained almost exactly as the Plotly example
def frame_args(duration):
return {
"frame": {"duration": duration},
"mode": "immediate",
"fromcurrent": True,
"transition": {"duration": duration, "easing": "linear"},
}
sliders = [
{
"pad": {"b": 10, "t": 60},
"len": 0.9,
"x": 0.1,
"y": 0,
"steps": [
{
"args": [[f.name], frame_args(0)],
"label": str(k),
"method": "animate",
}
for k, f in enumerate(fig.frames)
],
}
]
matrix_but = [
{"buttons: [{},{},{},{},{},{}]"}
]
# Layout
fig.update_layout(
title='Pivot de Gauss',
width=600,
height=400,
scene=dict(xaxis=dict(autorange=True),
yaxis=dict(autorange=True),
zaxis=dict(autorange=True),
aspectratio=dict(x=1, y=1, z=1),
),
updatemenus = [
{
"buttons": [
{
"args": [None, frame_args(200)],
"label": "▶", # play symbol
"method": "animate",
},
{
"args": [[None], frame_args(0)],
"label": "◼", # pause symbol
"method": "animate",
},
],
"direction": "left",
"pad": {"r": 10, "t": 70},
"type": "buttons",
"x": 0.1,
"y": 0,
}
],
sliders=sliders
)
fig.show()
You will notice that for each vector I first draw a 3D line and then use cone to get the it arrow_shaped. It might not be the best way to do it, but I do not want to use cone alone as the apsect does not fit what I would like.
I stumbled across a (I think) similar question here : https://community.plotly.com/t/only-one-trace-showing-per-frame-in-animated-plot/25803
But I did not undestand the answer nor the example.
It seems from what I get that only the first six elemetns of the data contained in each frame is taken into account, but I do not understand why and I would like to show everything.
If someone has some insight (and a solution) on the subject, it would be warmly welcomed.
I can clarify things if needed.
Image of the two first column vectors of matrix from current step and first column vector of matrix from previous step
Image of the three column vectors of current matrix when part below if k>0 is commented
It seems from what I get that only the first six elemetns of the data contained in each frame is taken into account, but I do not understand why and I would like to show everything.
There's this paragraph under the heading 'Current Animation Limitations and Caveats':
Animations are designed to work well when each row of input is present across all animation frames, and when categorical values mapped to symbol, color and facet are constant across frames. Animations may be misleading or inconsistent if these constraints are not met.
Though in your first frame you have only three vectors (three lines plus three coneheads) to plot, it violates the above constraint when following frames contain six vectors. To overcome this restriction, we could insert the three vectors in the first frame (and also in the data to be displayed before animation starts) twice, i. e. to the
if k>0 : # add column vectors of previous Gaussain elimination step (causes some troubles,
block add an
else:
dat.append(d1)
dat.append(d2)
block, and in the
if la.norm(v) != 0 :
block duplicate the two fig.add_trace calls.
I have a matrix (2d numpy ndarray, to be precise):
A = np.array([[4, 0, 0],
[1, 2, 3],
[0, 0, 5]])
And I want to roll each row of A independently, according to roll values in another array:
r = np.array([2, 0, -1])
That is, I want to do this:
print np.array([np.roll(row, x) for row,x in zip(A, r)])
[[0 0 4]
[1 2 3]
[0 5 0]]
Is there a way to do this efficiently? Perhaps using fancy indexing tricks?
Sure you can do it using advanced indexing, whether it is the fastest way probably depends on your array size (if your rows are large it may not be):
rows, column_indices = np.ogrid[:A.shape[0], :A.shape[1]]
# Use always a negative shift, so that column_indices are valid.
# (could also use module operation)
r[r < 0] += A.shape[1]
column_indices = column_indices - r[:, np.newaxis]
result = A[rows, column_indices]
numpy.lib.stride_tricks.as_strided stricks (abbrev pun intended) again!
Speaking of fancy indexing tricks, there's the infamous - np.lib.stride_tricks.as_strided. The idea/trick would be to get a sliced portion starting from the first column until the second last one and concatenate at the end. This ensures that we can stride in the forward direction as needed to leverage np.lib.stride_tricks.as_strided and thus avoid the need of actually rolling back. That's the whole idea!
Now, in terms of actual implementation we would use scikit-image's view_as_windows to elegantly use np.lib.stride_tricks.as_strided under the hoods. Thus, the final implementation would be -
from skimage.util.shape import view_as_windows as viewW
def strided_indexing_roll(a, r):
# Concatenate with sliced to cover all rolls
a_ext = np.concatenate((a,a[:,:-1]),axis=1)
# Get sliding windows; use advanced-indexing to select appropriate ones
n = a.shape[1]
return viewW(a_ext,(1,n))[np.arange(len(r)), (n-r)%n,0]
Here's a sample run -
In [327]: A = np.array([[4, 0, 0],
...: [1, 2, 3],
...: [0, 0, 5]])
In [328]: r = np.array([2, 0, -1])
In [329]: strided_indexing_roll(A, r)
Out[329]:
array([[0, 0, 4],
[1, 2, 3],
[0, 5, 0]])
Benchmarking
# #seberg's solution
def advindexing_roll(A, r):
rows, column_indices = np.ogrid[:A.shape[0], :A.shape[1]]
r[r < 0] += A.shape[1]
column_indices = column_indices - r[:,np.newaxis]
return A[rows, column_indices]
Let's do some benchmarking on an array with large number of rows and columns -
In [324]: np.random.seed(0)
...: a = np.random.rand(10000,1000)
...: r = np.random.randint(-1000,1000,(10000))
# #seberg's solution
In [325]: %timeit advindexing_roll(a, r)
10 loops, best of 3: 71.3 ms per loop
# Solution from this post
In [326]: %timeit strided_indexing_roll(a, r)
10 loops, best of 3: 44 ms per loop
In case you want more general solution (dealing with any shape and with any axis), I modified #seberg's solution:
def indep_roll(arr, shifts, axis=1):
"""Apply an independent roll for each dimensions of a single axis.
Parameters
----------
arr : np.ndarray
Array of any shape.
shifts : np.ndarray
How many shifting to use for each dimension. Shape: `(arr.shape[axis],)`.
axis : int
Axis along which elements are shifted.
"""
arr = np.swapaxes(arr,axis,-1)
all_idcs = np.ogrid[[slice(0,n) for n in arr.shape]]
# Convert to a positive shift
shifts[shifts < 0] += arr.shape[-1]
all_idcs[-1] = all_idcs[-1] - shifts[:, np.newaxis]
result = arr[tuple(all_idcs)]
arr = np.swapaxes(result,-1,axis)
return arr
I implement a pure numpy.lib.stride_tricks.as_strided solution as follows
from numpy.lib.stride_tricks import as_strided
def custom_roll(arr, r_tup):
m = np.asarray(r_tup)
arr_roll = arr[:, [*range(arr.shape[1]),*range(arr.shape[1]-1)]].copy() #need `copy`
strd_0, strd_1 = arr_roll.strides
n = arr.shape[1]
result = as_strided(arr_roll, (*arr.shape, n), (strd_0 ,strd_1, strd_1))
return result[np.arange(arr.shape[0]), (n-m)%n]
A = np.array([[4, 0, 0],
[1, 2, 3],
[0, 0, 5]])
r = np.array([2, 0, -1])
out = custom_roll(A, r)
Out[789]:
array([[0, 0, 4],
[1, 2, 3],
[0, 5, 0]])
By using a fast fourrier transform we can apply a transformation in the frequency domain and then use the inverse fast fourrier transform to obtain the row shift.
So this is a pure numpy solution that take only one line:
import numpy as np
from numpy.fft import fft, ifft
# The row shift function using the fast fourrier transform
# rshift(A,r) where A is a 2D array, r the row shift vector
def rshift(A,r):
return np.real(ifft(fft(A,axis=1)*np.exp(2*1j*np.pi/A.shape[1]*r[:,None]*np.r_[0:A.shape[1]][None,:]),axis=1).round())
This will apply a left shift, but we can simply negate the exponential exponant to turn the function into a right shift function:
ifft(fft(...)*np.exp(-2*1j...)
It can be used like that:
# Example:
A = np.array([[1,2,3,4],
[1,2,3,4],
[1,2,3,4]])
r = np.array([1,-1,3])
print(rshift(A,r))
Building on divakar's excellent answer, you can apply this logic to 3D array easily (which was the problematic that brought me here in the first place). Here's an example - basically flatten your data, roll it & reshape it after::
def applyroll_30(cube, threshold=25, offset=500):
flattened_cube = cube.copy().reshape(cube.shape[0]*cube.shape[1], cube.shape[2])
roll_matrix = calc_roll_matrix_flattened(flattened_cube, threshold, offset)
rolled_cube = strided_indexing_roll(flattened_cube, roll_matrix, cube_shape=cube.shape)
rolled_cube = triggered_cube.reshape(cube.shape[0], cube.shape[1], cube.shape[2])
return rolled_cube
def calc_roll_matrix_flattened(cube_flattened, threshold, offset):
""" Calculates the number of position along time axis we need to shift
elements in order to trig the data.
We return a 1D numpy array of shape (X*Y, time) elements
"""
# armax(...) finds the position in the cube (3d) where we are above threshold
roll_matrix = np.argmax(cube_flattened > threshold, axis=1) + offset
# ensure we don't have index out of bound
roll_matrix[roll_matrix>cube_flattened.shape[1]] = cube_flattened.shape[1]
return roll_matrix
def strided_indexing_roll(cube_flattened, roll_matrix_flattened, cube_shape):
# Concatenate with sliced to cover all rolls
# otherwise we shift in the wrong direction for my application
roll_matrix_flattened = -1 * roll_matrix_flattened
a_ext = np.concatenate((cube_flattened, cube_flattened[:, :-1]), axis=1)
# Get sliding windows; use advanced-indexing to select appropriate ones
n = cube_flattened.shape[1]
result = viewW(a_ext,(1,n))[np.arange(len(roll_matrix_flattened)), (n - roll_matrix_flattened) % n, 0]
result = result.reshape(cube_shape)
return result
Divakar's answer doesn't do justice to how much more efficient this is on large cube of data. I've timed it on a 400x400x2000 data formatted as int8. An equivalent for-loop does ~5.5seconds, Seberg's answer ~3.0seconds and strided_indexing.... ~0.5second.
How can I solve a system of linear equations with some Boundary conditions, using Numpy?
Ax=B
Where x is a column vector with, let's say x1=0.
For different iterations BCs are going to be different, so different variables of vector x going to be zero.
[A] and [B] are known.
Here is an example from my FEM course:
{F} Is the column vector of known values
[k] is the stiffness matrix with the known values
{U} is the displacement column vector where U1 and U3 are known to be zero, but U2 and U4 need to be found.
Here is an example:
This would result in these values:
Naturally this would reduce to the 2X2 matrix equation, but I because for different elements the BC would be different, I'm looking for some numpy matrix equation solver where I can let it know that some of the unknowns must be this certain value and nothing else.
Is there something similar to np.linalg.solve() with conditions to it?
Thank you.
the matrix k in your example is invertible. that means there is one and only one solution; you can not choose any of the Us. this is the solution:
import numpy as np
k = np.array(((1000, 0, -1000, 0),
(0, 3000, 0, -3000),
(-100, 0, 3000, -2000),
(0, -3000, -2000, 5000)))
F = np.array((0, 0, 0, 5000))
U = np.linalg.solve(k, F)
print(U)
# # or:
# k_inv = np.linalg.inv(k)
# U = k_inv.dot(F)
# [ 5.55555556 8.05555556 5.55555556 8.05555556]
the same in sage:
k = matrix(((1000, 0, -1000, 0),
(0, 3000, 0, -3000),
(-100, 0, 3000, -2000),
(0, -3000, -2000, 5000)))
F = vector((0, 0, 0, 5000))
U = k.inverse() * F
# (50/9, 145/18, 50/9, 145/18)
Trying to create Social graph using NetworkX in theory(as i think) everything is good works, but in practice works wrong.
So i've got information about some groups in such format:
members={'Group Name 1':[User 1 ID, User ID 2...],...,'Group Name N' : [User 1 ID,...,User K Id]}
For example:
members={'Group 1' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Group 2' : [10, 11, 12, 13, 14, 9],
'Group 3':[21,22,23,24] }
In outcome i need graph in which:
Vertices - Social Group
Edges - the existence of common subscribers (User IDs)
Vertices Size - Users Count
distance between Vertices - common Subscribers (User IDs)
My code:
matrix={}
for i in members:
for j in members:
if i!=j:
matrix[i+j]=len(set(members[i]) & set(members[j]))*1.0/min(len(set(members[i])),len(set(members[j])))
max_matrix = max(matrix.values())
min_matrix = min(matrix.values())
for i in matrix:
matrix[i] = (matrix[i] - min_matrix) / (max_matrix - min_matrix)
g = networkx.Graph(directed=False)
for i in members:
for j in members:
if i != j:
g.add_edge(i, j, weight=matrix[i+j])
members_count = {x:len(members[x]) for x in members}
max_value = max(members_count.values()) * 1.0
size = []
max_size = 900
min_size = 100
for node in g.nodes():
size.append(((members_count[node]/max_value)*max_size + min_size)*10)
import matplotlib.pyplot as plt
pos=networkx.spring_layout(g)
plt.figure(figsize=(20,20))
networkx.draw_networkx(g, pos, node_size=size, width=0.5, font_size=8)
plt.axis('off')
plt.show()
BUT, i can't understand why Edges drawing for groups which have no common IDs.
NetworkX only use weight as an attribute of edges. Whether there is an edge or not doesn't depend on edges' weights.
In other word, Those edges with weight 0 are also count as edges and it will be displayed by drawing function.