Python3 numpy array - python-3.x

I have a data file containing random values(without equal spacing) ranging between -5.07 to +6.01(390 values in total). I have to seperate these values according to some conditions like;
-5 to -4 as A
-4 to -3 as B etc.,
and finally add how many A/B/C... are present in total.
The codes are given below. On execution they are printing 'A' 390 times as output. Where is the error?
file = "86M"
v = np.loadtxt(file, delimiter = "\n")
A = B = C = 0
i = 0
while i < len(v):
if -5 < v[i] >= -4:
A = A+1
print (A)
i += 1

Related

Printing 6 first numbers from -20 to 20 using while loop

How can I print numerical interval from -20 to 20 using loop "while" and then print 6 first elements
I tried this to print numbers from -20 to 20 but still don't know how to print first six numbers.
x = -21
while x < 20:
x = x + 1
print(x)
Assign count = 6, decrease count after increasing and printing x, then use break if count is 0 or False:
x = -21
count = 6
while x < 20:
if not count: break
x += 1
count -= 1
print(x)
If you don't want to use if and break:
x = -21
count = 6
while x < 20 and count:
x += 1
count -= 1
print(x)
Or using count = 0 and increase it until 6:
x = -21
count = 0
while x < 20 and count < 6:
x += 1
count += 1
print(x)

Compare current value with n values above and below on Pandas DataFrame

I have this df:
x
0 2
1 2
2 2
3 1
4 1
5 2
6 2
I need to compare current value on column x with respect to the n previous and next values based on a defined condition, if condition is met q times then add 1 in a new column, if not, add 0.
For instance, if n is 2, q is 3 and the condition is current_value <= value / 2. In this case, the code will do 7 comparisons:
1st comparison: compare current_value = 2 to previous n = 2 numbers (in this case there are no such numbers because is the first value on the column) and then compare current_value = 2 to the next n = 2 values (in this case both numbers are 2, so condtion is not met on neither (2 <= 2/2)). In this case there are no conditions met, as q = 3 >= 0 the code adds 0 to the new column.
2nd comparison: compare current_value = 2 to previous n = 2 numbers (in this case there is just one number above, the condition is not met (2 <= 2/2)) and then compare current_value = 2 to the next n = 2 values (in this case there's a number 2 and then a number 1, so condition is not met (2 <= 2/2 and 2 <= 1/2)). In this case there are no conditions met, as q = 3 >= 0 the code adds 0 to the new column.
3rd comparison: In this case there are no condition met, as q = 3 >= 0 the code adds 0 to the new column.
4th comparison: compare current_value = 1 to previous n = 2 numbers (in this case there are two number 2 above, the condition is met on both of them (1 <= 2/2)) and then compare current_value = 1 to the next n = 2 values (in this case there's a number 1 and then a number 2, so condition is met once (1 <= 2/2 and 1 <= 1/2)). In this case there are 3 conditions met, as q = 3 >= 3 the code adds 1 to the new column.
5th comparison: In this case there are 3 conditions met, as q = 3 >= 3 the code adds 1 to the new column.
6th comparison: In this case there are no conditions met, as q = 3 >= 0 the code adds 0 to the new column.
7th comparison: In this case there are no conditions met, as q = 3 >= 0 the code adds 0 to the new column.
Desired result:
x comparison
0 2 0
1 2 0
2 2 0
3 1 1
4 1 1
5 2 0
6 2 0
I was thinking on using something like shift function but I'm not sure how to implement it. Any help?
I suggest to use numpy here, to benefit from its sliding window view:
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view as swv
n = 2
q = 3
# convert to numpy array
a = df['x'].astype(float).to_numpy()
# create a sliding window
# remove central value, divide by 2
# compare to original value
# count number of matches
count = (a[:,None] <= swv(np.pad(a, n, constant_values=np.nan), 2*n+1)[:, np.r_[:n,n+1:2*n+1]]/2).sum(1)
# array([0, 0, 0, 3, 3, 0, 0])
# compare number of matches to q
df['comparison'] = (count >= q).astype(int)
print(df)
An alternative with only pandas would require to compute two rolling windows (forward and backward) as it's not trivial to access the current index in a centered rolling with min_periods=1:
n = 2
q = 3
s1 = df['x'].rolling(n+1, min_periods=2).apply(lambda x: sum(x.iloc[-1]<=x.iloc[:-1]/2))
s2 = df.loc[::-1, 'x'].rolling(n+1, min_periods=2).apply(lambda x: sum(x.iloc[-1]<=x.iloc[:-1]/2))
df['comparison'] = s1.add(s2, fill_value=0).ge(3).astype(int)
Output:
x comparison
0 2 0
1 2 0
2 2 0
3 1 1
4 1 1
5 2 0
6 2 0

Using list instead of dictionary for organized results

I'm trying to get my code below working to have the results organized rather than random.
This is what's happening now.
sum = 9 count = 117
sum = 6 count = 142
sum = 3 count = 58
sum = 7 count = 172
sum = 8 count = 129
sum = 5 count = 109
sum = 4 count = 87
sum = 11 count = 53
sum = 12 count = 31
sum = 10 count = 72
And what I'm trying to achieve is
sum = 1 count = 117
sum = 2 count = 142
sum = 3 count = 58
sum = 4 count = 172
sum = 5 count = 129
sum = 6 count = 109
sum = 7 count = 87
sum = 8 count = 53
sum = 12 count = 31
etc. While omitting any number that hasn't been rolled.
I'd ideally like to use a list instead of a dictionary but any time I try it I get varying errors.
Currently this outputs the amount but not in order.
import random
print("results")
occurrences = []
for i in range(1000):
die1 = random.randint(1, 6)
die2 = random.randint(1, 6)
roll = die1 + die2
current = occurrences[roll, ]
occurrences[roll] = current + 1
for roll, count in occurrences[]
print(f"sum = {roll} count = {count}")
A recipe for dictionary-based roll occurrence counting would be:
First initialize all roll possibilities within a dictionary (the example below makes use of dictionary comprehension) where the dict keys are the roll value and the dict values are the corresponding occurence.
Count each time a roll happens with the +=1 statement (in-place add up 1).
Sort the dictionary with another dictionary comprehension operated on the sorted dictionary values (here, the occurrence of each roll).
Loop over the dictionary keys (rolls) and corresponding values (occurrences) in order to show the output.
Here is your code with the above statements included:
import random
print("results")
occurrences = {k: 0 for k in range(2, 13)}
for i in range(10000):
die1 = random.randint(1, 6)
die2 = random.randint(1, 6)
roll = die1 + die2
occurrences[roll] += 1
occurrences = {k: v for k, v in sorted(occurrences.items(), key=lambda item: item[1], reverse=True)}
for roll, count in occurrences.items():
print(f"sum = {roll} count = {count}")
which outputs the following result with 10,000 rolls:
sum = 7 count = 1653
sum = 6 count = 1398
sum = 8 count = 1325
sum = 5 count = 1162
sum = 9 count = 1142
sum = 10 count = 842
sum = 4 count = 812
sum = 11 count = 578
sum = 3 count = 540
sum = 2 count = 295
sum = 12 count = 253

Return values based on the sum of array indeces

I would like to return all values in an array where the row number plus the column number is a multiple of 5.
I feel like I'm close, but I can't seem to get the (i + j) % 5 == 0 part working as a condition.
using:
(i + j) % 5 == 0
I have constructed a random 8 x 9 array using:
arr2 = np.random.normal(size = (8,9), loc=1, scale=0.5)
a = np.empty([100,100])
for i in range(0,len(a)):
for j in range(0,len(a[0])):
if (i+j)%5 == 0:
print(i,j,i+j a[i][j])
output
0 0 0 0.0
0 5 5 0.0
0 10 10 0.0
0 15 15 0.0
0 20 20 0.0
.
.
.
I don't know what you did wrong you have the correct logic. Its a simple loop where you use the index itself as a test rather than than contents at that index.
Awesome thanks. I actually tweaked this a little to get the mean of all values that meet this criteria:
def arrmean5 (arr):
total = 0
count = 0
for i in range(0,len(arr)):
for j in range(0,len(arr[0])):
if (i+j) % 5 == 0:
total = total + (arr[i][j])
count += 1
return(total/count)
I appreciate the help Sam!

Print right-justified list of binary numbers

Here is the code to convert a decimal number number to binary (DectoBin), and to print a list of all binary numbers from 1 to number (print_formatted) :
def DectoBin(number):
j=1
binary = 0
while (number != 0):
reminder = number % 2
number= int(number / 2)
binary= binary + reminder * j
j *= 10
return(binary)
def print_formatted(number):
for j in range(1, number + 1):
bin1 = DectoBin(j)
print(bin1, end='\n')
Output I get :
1
10
11
100
101
110
111
1111
Output I want (right-justified list of binary numbers) :
1
10
11
100
101
110
111
1000
See PEP 498 which introduces Literal String Interpolation. You can use it to right justify your print out:
def DectoBin(number):
j=1
binary = 0
while (number != 0):
reminder = number % 2
number= int(number / 2)
binary= binary + reminder * j
j *= 10
return(binary)
for i in range(16):
print (f'{DectoBin(i):>5}')
which produces the following output:
0
1
10
11
100
101
110
111
1000
1001
1010
1011
1100
1101
1110
Define print_formatted function as following. This ensures that the binary numbers are correctly right justified with the right number of spaces before each number :
import math
def print_formatted(number):
max_bits = math.ceil(math.log2(number + 1))
for j in range(1, number + 1):
bin1 = str(DectoBin(j)).rjust(max_bits)
print(bin1, end='\n')
max_bits is the number of bits used to represent number, and rjust is used to right justify the string in a string of length max_bits.

Resources