I have the following array:
arr = [
[
[1, 2],
[3, 4],
[5, 6]
],
[
[7, 8],
[9, 10],
[11, 12]
],
[
[13, 14],
[15, 16],
[17, 18]
]
];
How can I reduce it the following using lodash:
[[9,12],[27,30],[45,48]]
I am a complete noob. I don't know what to do beyond this:
_.forEach(arr, function (n) {
console.log(JSON.stringify(_.zip(n)));
});
Some hints please.
Using a mix of lodash (_.unzip() and _.sum()) and Array methods (Array#map()):
var result = arr.map(function(a) {
return _.unzip(a).map(_.sum);
});
Similar to your attempt, combination of map, zipWith & add with some partialRight help :-)
var zipAdd = _.partialRight(_.zipWith, _.add)
var result = _.map(arr, function(a) {
return zipAdd.apply(null, a)
});
Working snippet
var arr = [
[
[1, 2],
[3, 4],
[5, 6]
],
[
[7, 8],
[9, 10],
[11, 12]
],
[
[13, 14],
[15, 16],
[17, 18]
]
];
var zipAdd = _.partialRight(_.zipWith, _.add)
var result = _.map(arr, function(a) {
return zipAdd.apply(null, a)
});
alert(JSON.stringify(result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js"></script>
Related
I have a pandas df, composed like:
X = pandas.DataFrame(
[
[1, "abc"],
[2, "abc"],
[3, "def"],
[4, "def"],
[5, "def"],
[6, "def"],
[7, "ghi"],
[8, "jkl"],
[9, "jkl"]
]
)
X.columns = ["id", "value"]
I want it to be a bit more memory friendly, in such a way that all the unique value items should just have their first instance present in the df, and rest of their consecutive instances be filled with an empty string.
Essentially, I would like to convert the above df into something like:
[
[1, "abc"],
[2, ""],
[3, ""],
[4, ""],
[5, ""],
[6, ""],
[7, "ghi"],
[8, "jkl"],
[9, ""]
]
My question is: Is there a panda-ized or some sort of dataframe-ish way of achieving this? I can totally convert it into the desired form by iterating over the dataframe, which I think (and actually is) a very slow process if your dataframe is actually large.
Please help. Thanks.
This would do :
X['value'] = X.value.where(X.value != X.value.shift(), '')
I'm building a rally custom HTML app. I would like to create a heat map chart. How can I do that?
I've tried to create Rally Chart of the type 'heatmap' (code below). As a result, I see the 404 error message in the console:
GET https://rally1.rallydev.com/slm/panel/highcharts/heatmap.js?_dc=1558434971290 404
When I try to use Highcharts library directly I'm getting a conflict with https://rally1.rallydev.com/apps/2.1/lib/analytics/analytics-all.js - highcharts being loaded twice. As a result analytics lib do not load I guess and I get an error like Lumenize.Time undefined.
this.chart = this.add(
Ext.create('Rally.ui.chart.Chart', {
loadMask: false,
chartData: {
series: [{
type:'heatmap',
name: 'Sales per employee',
borderWidth: 1,
data: [[0, 0, 10], [0, 1, 19], [0, 2, 8], [0, 3, 24], [0, 4, 67], [1, 0, 92], [1, 1, 58], [1, 2, 78], [1, 3, 117], [1, 4, 48], [2, 0, 35], [2, 1, 15], [2, 2, 123], [2, 3, 64], [2, 4, 52], [3, 0, 72], [3, 1, 132], [3, 2, 114], [3, 3, 19], [3, 4, 16], [4, 0, 38], [4, 1, 5], [4, 2, 8], [4, 3, 117], [4, 4, 115], [5, 0, 88], [5, 1, 32], [5, 2, 12], [5, 3, 6], [5, 4, 120], [6, 0, 13], [6, 1, 44], [6, 2, 88], [6, 3, 98], [6, 4, 96], [7, 0, 31], [7, 1, 1], [7, 2, 82], [7, 3, 32], [7, 4, 30], [8, 0, 85], [8, 1, 97], [8, 2, 123], [8, 3, 64], [8, 4, 84], [9, 0, 47], [9, 1, 114], [9, 2, 31], [9, 3, 48], [9, 4, 91]],
dataLabels: {
enabled: true,
color: '#000000'
}
}]
},
chartConfig: {
chart: {
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 1
},
title: {
text: 'Sales per employee per weekday'
},
xAxis: {
categories: ['Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas', 'Maria', 'Leon', 'Anna', 'Tim', 'Laura']
},
yAxis: {
categories: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
title: null
},
colorAxis: {
min: 0,
minColor: '#FFFFFF',
//maxColor: Highcharts.getOptions().colors[0]
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 280
},
tooltip: {
formatter: function () {
return '<b>' + this.series.xAxis.categories[this.point.x] + '</b> sold <br><b>' +
this.point.value + '</b> items on <br><b>' + this.series.yAxis.categories[this.point.y] + '</b>';
}
},
}
})
);
The problem you are going to hit is that the Highcharts v3.0.10 is bundled into the analytics code. This has been done so that there is a known Highcharts library used with the added Lumenize code - i.e. they match. The analytics library is dynamically loaded if the SDK can't find a Highcharts library as it starts up (i.e. window.Highcharts is undefined).
The result of this is that it looks like it is quite kludgy to change the Highcharts arrangement to add heatmaps. Someone who is better at javascript library loading/overloading might have a different view. You would have to load the heatmap.js file into your app after the app has started (in 'launch'?) to get around the dynamic loading.
I know that this is not directly related to your Highcharts question, but if it is just a 'heatmap' you are after, not necessarily a Highcharts heatmap, I have started to use d3 to visualise stuff in Rally. There is a d3 heatmap example here if you are interested: http://bl.ocks.org/tjdecke/5558084
I have done a bit of work to get d3 working inside a Rally custom app. There are a few examples on my github, but have a look here: https://github.com/nikantonelli/Radial-Density
a = np.arange(12).reshape(2,3,2)
[[[ 0 1]
[ 2 3]
[ 4 5]]
[[ 6 7]
[ 8 9]
[10 11]]]
how to exchange position of [4 5] and [10 11] use numpy? Thanks
Those rows can be sliced with:
In [1418]: a[:,2,:]
Out[1418]:
array([[ 4, 5],
[10, 11]])
viewed in reverse order with:
In [1419]: a[::-1,2,:]
Out[1419]:
array([[10, 11],
[ 4, 5]])
and replaced with:
In [1420]: a[:,2,:] = a[::-1,2,:]
In [1421]: a
Out[1421]:
array([[[ 0, 1],
[ 2, 3],
[10, 11]],
[[ 6, 7],
[ 8, 9],
[ 4, 5]]])
I have a 3d array
A = np.random.random((4,4,3))
and a index matrix
B = np.int_(np.random.random((4,4))*3)
How do I get a 2D array from A based on index matrix B?
In general, how to get a N-1 dimensional array from a ND array and a N-1 dimensional index array?
Lets take an example:
>>> A = np.random.randint(0,10,(3,3,2))
>>> A
array([[[0, 1],
[8, 2],
[6, 4]],
[[1, 0],
[6, 9],
[7, 7]],
[[1, 2],
[2, 2],
[9, 7]]])
Use fancy indexing to take simple indices. Note that the all indices must be of the same shape and the shape of each index will be what is returned.
>>> ind = np.arange(2)
>>> A[ind,ind,ind]
array([0, 9]) #Index (0,0,0) and (1,1,1)
>>> ind = np.arange(2).reshape(2,1)
>>> A[ind,ind,ind]
array([[0],
[9]])
So for your example we need to supply the grid for the first two dimensions:
>>> A = np.random.random((4,4,3))
>>> B = np.int_(np.random.random((4,4))*3)
>>> A
array([[[ 0.95158697, 0.37643036, 0.29175815],
[ 0.84093397, 0.53453123, 0.64183715],
[ 0.31189496, 0.06281937, 0.10008886],
[ 0.79784114, 0.26428462, 0.87899921]],
[[ 0.04498205, 0.63823379, 0.48130828],
[ 0.93302194, 0.91964805, 0.05975115],
[ 0.55686047, 0.02692168, 0.31065731],
[ 0.92822499, 0.74771321, 0.03055592]],
[[ 0.24849139, 0.42819062, 0.14640117],
[ 0.92420031, 0.87483486, 0.51313695],
[ 0.68414428, 0.86867423, 0.96176415],
[ 0.98072548, 0.16939697, 0.19117458]],
[[ 0.71009607, 0.23057644, 0.80725518],
[ 0.01932983, 0.36680718, 0.46692839],
[ 0.51729835, 0.16073775, 0.77768313],
[ 0.8591955 , 0.81561797, 0.90633695]]])
>>> B
array([[1, 2, 0, 0],
[1, 2, 0, 1],
[2, 1, 1, 1],
[1, 2, 1, 2]])
>>> x,y = np.meshgrid(np.arange(A.shape[0]),np.arange(A.shape[1]))
>>> x
array([[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]])
>>> y
array([[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3]])
>>> A[x,y,B]
array([[ 0.37643036, 0.48130828, 0.24849139, 0.71009607],
[ 0.53453123, 0.05975115, 0.92420031, 0.36680718],
[ 0.10008886, 0.02692168, 0.86867423, 0.16073775],
[ 0.26428462, 0.03055592, 0.16939697, 0.90633695]])
If you prefer to use mesh as suggested by Daniel, you may also use
A[tuple( np.ogrid[:A.shape[0], :A.shape[1]] + [B] )]
to work with sparse indices. In the general case you could use
A[tuple( np.ogrid[ [slice(0, end) for end in A.shape[:-1]] ] + [B] )]
Note that this may also be used when you'd like to index by B an axis different from the last one (see for example this answer about inserting an element into a list).
Otherwise you can do it using broadcasting:
A[np.arange(A.shape[0])[:, np.newaxis], np.arange(A.shape[1])[np.newaxis, :], B]
This may be generalized too but it's a bit more complicated.
I have a question regarding how to extract certain values from a 2D numpy array
Foo =
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]])
Bar =
array([[0, 0, 1],
[1, 2, 3]])
I want to extract elements from Foo using the values of Bar as indices, such that I end up with an 2D matrix/array Baz of the same shape as Bar. The ith column in Baz correspond is Foo[(np.array(each j in Bar[:,i]),np.array(i,i,i,i ...))]
Baz =
array([[ 1, 2, 6],
[ 4, 8, 12]])
I could do a couple nested for-loops but I was wondering if there is a more elegant, numpy-ish way to do this.
Sorry if this is a bit convoluted. Let me know if I need to explain further.
Thanks!
You can use Bar as the row index and an array [0, 1, 2] as the column index:
# for easy copy-pasting
import numpy as np
Foo = np.array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9], [10, 11, 12]])
Bar = np.array([[0, 0, 1], [1, 2, 3]])
# now use Bar as the `i` coordinate and 0, 1, 2 as the `j` coordinate:
Foo[Bar, [0, 1, 2]]
# array([[ 1, 2, 6],
# [ 4, 8, 12]])
# OR, to automatically generate the [0, 1, 2]
Foo[Bar, xrange(Bar.shape[1])]