How to generate an nd-array where values are greater than 1? [duplicate] - python-3.x

This question already has answers here:
Generate random array of floats between a range
(10 answers)
Closed 2 years ago.
Is it possible to generate random numbers in an nd-array such the elements in the array are between 1 and 2 (The interval should be between 1 and some number greater than 1 )? This is what I did.
input_array = np.random.rand(3,10,10)
But the values in the nd-array are between 0 and 1.
Please let me know if that is possible. Any help and suggestions will be highly appreciated.

You can try scaling:
min_val, max_val = 1, 2
input_array = np.random.rand(3,10,10) * (mal_val-min_val) + min_val
or use uniform:
input_array = np.random.uniform(min_val, max_val, (3,10,10))

You can use np.random.randInt() in order to generate nd array with random integers
import numpy as np
rand_arr=np.random.randint(low = 1, high = 10, size = (10,10))
print(rand_arr)
# It changes randomly
#Output:
[[6 9 3 4 9 2 6 2 9 7]
[7 1 7 1 6 2 4 1 8 6]
[9 5 8 3 5 9 9 7 8 4]
[7 3 6 9 9 4 7 2 8 5]
[7 7 7 4 6 6 6 7 2 5]
[3 3 8 5 8 3 4 5 4 3]
[7 8 9 3 5 8 3 5 7 9]
[3 9 7 1 3 6 3 1 4 6]
[2 9 3 9 3 6 8 2 4 8]
[6 3 9 4 9 5 5 6 3 7]]

Related

New DataFrame column that contains IDs where value is outside bounds?

I have the following DataFrame :
data: Dict[str, list[int]] = {
"x1": [5 , 6, 7, 8, 9],
"min1": [3 , 3, 3, 3, 3],
"max1": [8, 8, 8, 8, 8],
"x2": [0 , 1, 2, 3, 4],
"min2": [2 , 2, 2, 2, 2],
"max2": [7, 7, 7, 7, 7],
"x3": [7 , 6, 7, 6, 7],
"min3": [1 , 1, 1, 1, 1],
"max3": [6, 6, 6, 6, 6],
}
n: int = 3 # number of xi
df: pd.DataFrame = pd.DataFrame(data=data)
print(df)
Output
x1 min1 max1 x2 min2 max2 x3 min3 max3
0 5 3 8 0 2 7 7 1 6
1 6 3 8 1 2 7 6 1 6
2 7 3 8 2 2 7 7 1 6
3 8 3 8 3 2 7 6 1 6
4 9 3 8 4 2 7 7 1 6
I would like to add a new column alert to df that contains the IDs i where xi < mini or xi > maxi.
Expected result
x1 min1 max1 x2 min2 max2 x3 min3 max3 alert
0 5 3 8 0 2 7 7 1 6 "2,3"
1 6 3 8 1 2 7 6 1 6 "2"
2 7 3 8 2 2 7 7 1 6 "3"
3 8 3 8 3 2 7 6 1 6 ""
4 9 3 8 4 2 7 7 1 6 "1,3"
I looked at this answer but could not understand how to apply it to my problem.
Below is my working implementation that I wish to improve.
def f(row: pd.Series) -> str:
alert: str = ""
for k in range(1, n+1):
if row[f"x{k}"] < row[f"min{k}"] or row[f"x{k}"] > row[f"max{k}"]:
alert += f"{k}"
return ",".join(list(alert))
df["alert"] = df.apply(f, axis=1)
Actually given your output as strings, your approach isn't too bad. I would just suggest making alert a list, not a string:
def f(row: pd.Series) -> str:
alert: list = []
for k in range(1, n+1):
if row[f"x{k}"] < row[f"min{k}"] or row[f"x{k}"] > row[f"max{k}"]:
alert.append(f"{k}")
return ",".join(alert)
In a bit fancy way, you can do:
xs = df.filter(regex='^x')
mins = df.filter(like='min').to_numpy()
maxes = df.filter(like='max').to_numpy()
mask = (xs < mins) | (xs > maxes)
df['alert'] = ( mask # xs.columns.str.replace('x',',')).str.replace('^,','')
We can groupby to dataframe along columns according to integer it contains
df['alert'] = (df.groupby(df.columns.str.extract('(\d+)$')[0].tolist(), axis=1)
.apply(lambda g: g[f'x{g.name}'].le(g[f'min{g.name}']) | g[f'x{g.name}'].gt(g[f'max{g.name}']))
.apply(lambda row: ','.join(row.index[row]), axis=1))
print(df)
x1 min1 max1 x2 min2 max2 x3 min3 max3 alert
0 5 3 8 0 2 7 7 1 6 2,3
1 6 3 8 1 2 7 6 1 6 2
2 7 3 8 2 2 7 7 1 6 2,3
3 8 3 8 3 2 7 6 1 6
4 9 3 8 4 2 7 7 1 6 1,3
Intermediate result
(df.groupby(df.columns.str.extract('(\d+)$')[0].tolist(), axis=1)
.apply(lambda g: g[f'x{g.name}'].le(g[f'min{g.name}']) | g[f'x{g.name}'].gt(g[f'max{g.name}'])))
1 2 3
0 False True True
1 False True False
2 False True True
3 False False False
4 True False True
Using pandas:
a = (pd.wide_to_long(df.reset_index(), ['x', 'min', 'max'],'index', 'alert')
.loc[lambda x: x['x'].lt(x['min']) | x['x'].gt(x['max'])]
.reset_index()
.groupby('index')['alert'].agg(lambda x: ','.join(x.astype(str))))
df.join(a)
x1 min1 max1 x2 min2 max2 x3 min3 max3 alert
0 5 3 8 0 2 7 7 1 6 2,3
1 6 3 8 1 2 7 6 1 6 2
2 7 3 8 2 2 7 7 1 6 3
3 8 3 8 3 2 7 6 1 6 NaN
4 9 3 8 4 2 7 7 1 6 1,3

pd.Series(pred).value_counts() how to get the first column in dataframe?

I apply pd.Series(pred).value_counts() and get this output:
0 2084
-1 15
1 13
3 10
4 7
6 4
11 3
8 3
2 3
9 2
7 2
5 2
10 2
dtype: int64
When I create a list I get only the second column:
c_list=list(pd.Series(pred).value_counts()), Out:
[2084, 15, 13, 10, 7, 4, 3, 3, 3, 2, 2, 2, 2]
How do I get ultimately a dataframe that looks like this including a new column for size% of total size?
df=
[class , size ,relative_size]
0 2084 , x%
-1 15 , y%
1 13 , etc.
3 10
4 7
6 4
11 3
8 3
2 3
9 2
7 2
5 2
10 2
You are very nearly there. Typing this in the blind as you didn't provide a sample input:
df = pd.Series(pred).value_counts().to_frame().reset_index()
df.columns = ['class', 'size']
df['relative_size'] = df['size'] / df['size'].sum()

Need to create incremental series number using python

I need to create a incremental series for a given value of dataframe in python.
Any help much appreciated
Suppose I have dataframe column
df['quadrant']
Out[6]:
0 4
1 4
2 4
3 3
4 3
5 3
6 2
7 2
8 2
9 1
10 1
11 1
I want to create a new column such that
index quadrant new value
0 4 1
1 4 5
2 4 9
3 3 2
4 3 6
5 3 10
6 2 3
7 2 7
8 2 11
9 1 4
10 1 8
11 1 12
Using Numpy, you can create the array as:
import numpy as np
def value(q, k=1):
diff_quadrant = np.diff(q)
j = 0
ramp = []
for i in np.where(diff_quadrant != 0)[0]:
ramp.extend(list(range(i-j+1)))
j = i+1
ramp.extend(list(range(len(quadrant)-j)))
ramp = np.array(ramp) * k # sawtooth-shaped array
a = np.ones([len(quadrant)], dtype = np.int)*5
return a - q + ramp
quadrant = np.array([3, 3, 3, 3, 4, 4, 4, 2, 2, 1, 1, 1])
b = value(quadrant, 4)
# [ 2 6 10 14 1 5 9 3 7 4 8 12]

I want to export my Data in a Cell Array to an Excel file, as tidy as possible, without semi-colons for new rows

I have a Cell Array of dimensions 2 by 40, and each cell contains a matrix of dimensions 3 by 3:
[3x3 double] [3x3 double] [3x3 double] ... [3x3 double]
[3x3 double] [3x3 double] [3x3 double] ... [3x3 double]
Now, I need to print this Cell Array and show it to my study group. Below is the detailed example of what I am trying to achieve.
Print should show each matrix in the cell clearly and separately, so that we can study it better, similar to this:
[1 2 3] [5 2 3]
[4 5 6] [1 2 2] ...
[7 8 9] [7 8 9]
[5 2 3] [4 5 6]
[3 5 6] [7 2 9] ...
[7 1 9] [5 2 3]
I tried converting Cell to Table, unfortunately this was untidy, as it showed each new row of matrices with semi-colons:
[1 2 3; 4 5 6; 7 8 9]
Also, I tried converting Cell to Double with:
data = [cell{1,:};cell{2,:}];
resulting in 6 by 120 double, looking like this:
1 2 3 5 2 3
4 5 6 1 2 2 ...
7 8 9 7 8 9
5 2 3 2 5 6
3 5 6 7 2 9 ...
7 1 9 5 2 3
I can export this to an Excel file, however you can see that it is still cumbersome. I can cut and paste the rows 4,5,6 and shift them below so that it looks like:
1 2 3 5 2 3
4 5 6 1 2 2 ...
7 8 9 7 8 9
5 2 3 2 5 6
3 5 6 7 2 9 ...
7 1 9 5 2 3
however I still need to divide every other 3 columns, so that I can achieve what I want, which is very impractical:
1 2 3 5 2 3
4 5 6 1 2 2 ...
7 8 9 7 8 9
5 2 3 2 5 6
3 5 6 7 2 9 ...
7 1 9 5 2 3
I would really appreciate your help on this one. Thank you in advance.
To display a complex cell array like this, you can use celldisp to display the cell in an understandable way.
% Create some example data
D = arrayfun(#(x)rand(3,3), ones(2,2), 'uni', 0);
% Display it
celldisp(D)
Another possible way to display this is to create a custom little routine to print the data.
formatspec = '%10.4f';
format = repmat([repmat([formatspec ' '], [1 size(D{1},2)]), ' '], [1 size(D,2)]);
arrayfun(#(k)fprintf('%s\n', sprintf([format, '\n'], cat(2, D{k,:}).')), 1:size(D,1))
A third option, if you really want to export to Excel, you will want to alter the fprintf statement to create a CSV file.
fid = fopen('data.csv', 'w');
% Create the format specifier for a row
format = repmat([repmat('%0.4f,', [1 size(D{1}, 2)]), ','], [1 size(D,2)]);
format(end-1:end) = '';
for k = 1:size(D, 1)
fprintf(fid, [format '\n'], cat(2, D{k,:}).');
% Create an empty row
fprintf(fid, ',\n');
end
fclose(fid);
The result when loaded in Excel.

How change an arbitrary range of values to ranged values?

I am going to convert an array as [1 2 6 12 13 15 20 8 30 31] to range [1 2 3 4 5 6 7 8 9 10] in EXCEL or in MATLAB. Is there any function to do it? Is there any suggestion to convert this type of arbitrary range to definite range?
Solution for MATLAB
In MATLAB, unique can do the trick. For example:
A = [1 1 1 1 4 4 5 3 3 6 6 6 6 8]
[C, ia, ic] = unique(A);
Now ic holds the values that you're looking for:
ic =
1 1 1 1 3 3 4 2 2 5 5 5 5 6
Also, you can remap ic to a new order if you wish to do so. For instance, here's a new order similar to the one you suggested:
new_order = [1 3 2 4 6 5];
ic_new = new_order(ic);
which yields:
ic_new =
1 1 1 1 2 2 4 3 3 6 6 6 6 5
Hope that helps!
In Matlab:
v = [1 2 6 12 13 15 20 8 30 31];
v_index = 1:length(v);

Resources