Loop for mean for each level: Python - python

I have a panda dataframe with all these attributes:
The variable are bd, ce, n, od, ph and sc but i have their value for differents depths: (0-5cm, 5-15cm, 15-30cm, 30-60cm, 60-100cm, 100-200cm).
So, six collections of attributes like:
bd_0_5
bd_5_15
bd_15_30
bd_30_60
bd_60_100
bd_100_200
I would like to calculate the mean value of each variable for the observation depth.
For example: I have an observation (core drilling) that is made from 10 to 70cm. So i would like to add in my pandas dataframe 6 columns bdo, ce, n, od, ph and sc. In each of these columns i would like to have the mean of each attribute.
for an observation from 10 to 70cm the value of ph have to be built as follow:
ph = (
(ph_0_5 * 0) +
(ph_5_15 * 5) +
(ph_15_30 * 15) +
(ph_30_60 * 30) +
(ph_60_100 * 10) +
(ph_100_200 * 0)) / (70-10)
to do this i have wrote this code:
name = ["ph", "ce","sc","n","od","bd"]
udg = [0, 5, 15, 30, 60, 100]
ldg = [5, 15, 30, 60, 100, 200]
counter = list(range(0,43114))
for nm in name:
df[nm] = 0
for i in counter:
value = 0
for u, l in zip(udg, ldg):
if (df["upper_dept"].iloc[i]<=u) & (df["lower_dept"].iloc[i]>=l): #case 1: sample contain the interval
value = value + ((l - u) * df.eval(nm + "_" + str(u) + "_" + str(l)).iloc[i])
elif (df["upper_dept"].iloc[i]>u) & (df["lower_dept"].iloc[i]>=l): #case 2: sample start in the interval
value = value + ((l - df["upper_dept"].iloc[i]) * df.eval(nm + "_" + str(u) + "_" + str(l)).iloc[i])
elif (df["upper_dept"].iloc[i]<=u) & (df["lower_dept"].iloc[i]<l): #case 3: sample end in the interval
value = value + ((u - df["lower_dept"].iloc[i]) * df.eval(nm + "_" + str(u) + "_" + str(l)).iloc[i])
df[nm].iloc[i] = (value / (df["lower_dept"].iloc[i] - df["upper_dept"].iloc[i]))
The code work but the results have no sense and sometimes are negatives, in my mind the loop are correct. Can someone pls fix my code? :)

Related

Trying to use Zeller’s formula to return days of the week using python

I see java codes but can't fully compare them with python. I am trying to use the Zeller’s Congruence to find the day of the week for any date.
Zeller’s formula assumes that for each computation within the formula where there is a
quotient (or a division of two numbers), the integer value of that computation is used. If the month is January or February then 12 is added to the month and 1
subtracted from year before calculating day.
day = (((13*m+3) / 5 + d + y + (y / 4) - (y / 100) + (y / 400)) %7).
day_names =[('Monday'),'Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']
for example day_names[0] = 'Monday' and day_names[6] = 'Sunday'
The below does not seem to ever give me the correct dates, is there anyone who might be able to tell what I am doing wrong if not everything?
def day_of_week1(d, m, y):
d=1<=d<=31
m=1<=m<=12
y=1<=y<=10**5
if m in range (1,2):
m=m+12
y=y-1
day_names =[('Monday'),'Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']
day =(((13*m+3) / 5 + d + y + (y / 4) - (y / 100) + (y / 400)) %7)
day=(math.ceil(day))
if 2>day>=1:
return day_names[0]
elif 3>day>=2:
return day_names[1]
elif 4>day>=3:
return day_names[2]
elif 5>day>=4:
return day_names[3]
elif 6>day>=5:
return day_names[4]
elif 7>day>=6:
return day_names[5]
elif 8>day>=7:
return day_names[6]
Use the day names from the calendar module. Also, the adjustment for the month is not compliant with Zeller's Rule. Try this:
import calendar
def day_of_week(d, m, y):
if m < 3:
y -= 1
m += 10
else:
m -= 2
yc, yd = divmod(y, 100)
r = d + (13 * m - 1) // 5 + yd + yd // 4 + yc // 4 - 2 * yc
return calendar.day_name[r % 7 - 1]
print(day_of_week(9, 11, 1951))
Output:
Friday

How to print two columns with different range using for loops?

I need some very basic help with Python. I'm trying to get a better understanding of formatting using a for loop and I want to print out vertical Histogram.
Here is what I've tried:
tot_progress = 2
tot_trailer = 4
tot_retriever = 3
tot_exclude = 4
# Vertical Histogram
print("Progress", " Trailing", " Retriever", " Excluded")
a = '*'
for i,j,k,l in zip(range(0, tot_progress, 1), range(0, tot_trailer, 1), range(0, tot_retriever, 1), range(0, tot_exclude, 1)):
print('{}\t\t\t{}\t\t\t{}\t\t\t{}'.format(a, a, a, a))
The output I got:
Progress Trailing Retriever Excluded
* * * *
* * * *
what I want:
Progress Trailing Retriever Excluded
* * * *
* * * *
* * *
* *
User itertools longest to iterate to maximum and update your loop with conditions and print accordingly
import itertools
for i,j,k,l in itertools.zip_longest(range(0, tot_progress, 1), range(0, tot_trailer, 1), range(0, tot_retriever, 1), range(0, tot_exclude, 1)):
ai="*" if not i == None else " "
aj="*" if not j == None else " "
ak="*" if not k == None else " "
al="*" if not l == None else " "
print('{}\t\t\t{}\t\t\t{}\t\t\t{}'.format(ai, aj, ak, al))
In order to have vertical histograms you can format each row to have the same "length" and then zip, so that you can transpose it properly. Used string formatting layout, see here for details.
Each bar of the histogram will be centered wrt to the label of the column.
col_labels = {'Progress statussss': 2, "Trailing": 8, "Retriever": 3, "Excluded": 4}
SYMBOL = '*'
PADDING = 2 # add extra space between two columns
col_sizes = list(map(len, col_labels))
row_template = [(('{S:^' + f'{size + PADDING}' + '}' + ' ') *v)[:-1].split() + [' ' * (size+PADDING) ]*(size - v) for size, v in zip(col_sizes, col_labels.values())]
# column names
print(''.join(('{:^' + f'{col_sizes[i] + PADDING}' + '}').format(v) for i, v in enumerate(col_labels)))
# bars
for l in (''.join(i) for i in zip(*row_template)):
print(l.format(S=SYMBOL))
Output
Progress statussss Trailing Retriever Excluded
* * * *
* * * *
* * *
* *
*
*
*
*

Mean from a list with a condition in Python

list = [[159.2213, 222.2223, 101.2122]
[359.2222, 22.2210, 301.2144]]
if list[1][0] < list[0][0]:
avg = (list[1][0] + list[0][0] - 200)/2
else:
avg = (list[1][0] + list[0][0] + 200)/2
Hello! I want to do this for every column and output the results in another list.
Fix
You may loop iterate the number of cols there is
values = [[159.2213, 222.2223, 101.2122], [359.2222, 22.2210, 301.2144]]
avgs = []
for idx_col in range(len(values[0])):
if values[1][idx_col] < values[0][idx_col]:
avg = (values[1][idx_col] + values[0][idx_col] - 200) / 2
else:
avg = (values[1][idx_col] + values[0][idx_col] + 200) / 2
avgs.append(avg)
Simplify
You can use zip to iterate on both rows at a time, and simplify the if/else condition
avgs = []
for first_row, second_row in zip(*values):
factor = -1 if second_row < first_row else 1
avgs.append((first_row + second_row + (200 * factor)) / 2)
Best with numpy
Easy syntax and best performance
import numpy as np
values = np.array(values)
res = values.sum(axis=0) / 2
res += np.where(values[1] < values[0], -100, 100)
A list comprehension would look like this:
avg = [(x + y + (200 if x <= y else -200)) / 2 for x, y in zip(*lst)]
Arguably easier if you use numpy:
arr = np.array(lst)
avg = 0.5 * (arr.sum(axis=0) + np.copysign(200, np.diff(arr, axis=0)))
lis = [[159.2213, 222.2223, 101.2122],
[359.2222, 22.2210, 301.2144]]
res = []
for i in range(len(lis[0])):
if lis[1][i] < lis[0][i]:
res.append((lis[1][i] + lis[0][i] - 200)/2)
else:
res.append((lis[1][i] + lis[0][i] + 200)/2)
This should work, however using numpy would be a better solution for these kind of problems.
You can do it like this:
list = [[159.2213, 222.2223, 101.2122]
[359.2222, 22.2210, 301.2144]]
results = []
for x,y in zip(list[0],list[1]):
if y < x:
avg = (y + x - 200)/2
else:
avg = (y + x + 200)/2
results.append(avg)

ErlangC Python Function

The objective of this is to increase Variable N by 1 until the result is equal to Variable SLT or just under SLT. I am new at python, but this is what I came up with:
from math import factorial
import math
{A = 10
N = 11
TGT = 20
SLT = .80
AHT = 180
}
def ErlangC():
if (N-A<=0):
return 1
else:
L = (A**N / factorial(N)) * (N / (N - A))
sum_ = 0
for i in range(N):
sum_ += (A**i) / factorial(i)
return (1 - (L / (sum_ + L)) * math.exp((-(N-A) * (TGT / AHT))))
ErlangC()
the idea behind it is making a while loop until the required service level is achieved, you can use pyworkforce which already has this function implemented, example:
Example:
from pyworkforce.queuing import ErlangC
erlang = ErlangC(transactions=100, asa=20/60, aht=3, interval=30, shrinkage=0.3)
positions_requirements = erlang.required_positions(service_level=0.8, max_occupancy=0.85)
print("positions_requirements: ", positions_requirements)
Output:
>> positions_requirements: {'raw_positions': 14,
'positions': 20,
'service_level': 0.8883500191794669,
'occupancy': 0.7142857142857143,
'waiting_probability': 0.1741319335950498}

How to draw this bow tie pattern using Python 2.7?

I need to draw the following pattern using Python While Loops.
I have spent quite a lot of time and came up with this code which prints it perfectly but this code is so much long and I feel like it is not one of those good codes.
If anybody here can help me out shrinking this code or suggesting a better way to output?
here is the code:
#Question 10, Alternate Approach
temp = 1
pattern = ""
innerSpace = 7
starCount = 1
while temp <= 5:
st = 1
while st <= starCount:
pattern = pattern + "*"
if st != starCount:
pattern = pattern + " "
st = st + 1
sp = 0
if temp == 5:
innerSpace = 1
while sp < innerSpace:
pattern = pattern + " "
sp = sp + 1
st = 1
while st <= starCount:
if temp == 5:
st = st + 1
pattern = pattern + "*"
if st != starCount:
pattern = pattern + " "
st = st + 1
temp = temp + 1
innerSpace = innerSpace - 2
pattern = pattern + "\n"
if temp % 2 == 0:
pattern = pattern + " "
else:
starCount = starCount + 1
starCount = 2
innerSpace = 1
while temp > 5 and temp <= 9:
st = 1
while st <= starCount:
pattern = pattern + "*"
if st != starCount:
pattern = pattern + " "
st = st + 1
sp = 0
while sp < innerSpace:
pattern = pattern + " "
sp = sp + 1
st = 1
while st <= starCount:
pattern = pattern + "*"
if st != starCount:
pattern = pattern + " "
st = st + 1
temp = temp + 1
innerSpace = innerSpace + 2
pattern = pattern + "\n"
if temp % 2 == 0:
starCount = starCount - 1
pattern = pattern + " "
print pattern
Since this looks like an assignment, I'll give you a hint how I would do it.
Take advantage of the symmetry of the bow. It is symmetrical about the horizontal and vertical axis. Therefore, you really only need to solve 1 corner, then copy/mirror the results to get the rest.
This code gives one way of looking at the problem, which is just shifting a initial string (the middle of the bow) to get the desired shape:
m = '*'
size = 4
n = 5 # must be odd
pad = ' ' * n
middle = (m + pad) * size
half = int(n / 2) + 1
print middle
print middle[half*1:]
print middle[half*2:]
print middle[half*3:]
print middle[half*4:]
print middle[half*5:]
print middle[half*6:]
Which yields this:
* * * *
* * *
* * *
* *
* *
*
*
Good luck!
I would use list comprehensions and strings and would exploit the symmetry of the figure.
Not a complete solution, but could be a part of a loop body
In [2]: a = '*' + ' '*8
In [3]: a
Out[3]: '* '
In [24]: result = ''
In [25]: result += a
In [26]: result
Out[26]: '* '
In [27]: result += a[-1::-1]
In [28]: result
Out[28]: '* *'
In [29]: result += '\n'
In [30]: a = ' '+'*' + ' '*7
In [31]: a
Out[31]: ' * '
In [32]: result += a
In [33]: result += a[-1::-1]
In [34]: result += '\n'
In [36]: print result
* *
* *
IMHO you use while loop much as if they where for loops.
I don't think that's what your teacher wants.
The idea behind while is to run until a certain condition is met, not
necessarily when the number of iterations exceed a certain limit.
The condition does not need to be included in the while statement, you can check it later and use the break command to escape the loop
Try for example this:
start = '*'
while True:
print start
if start[0] == '*':
start = ' ' + start
else:
start = '*' + start
if (start == '* * *'):
break
output is just a part of your assignment, think you should be able to work it out to the final, expected result!
Hopefully by this time HW is done. Since I solved this using dynamic programming, I thought I would list solution here.
Observations:
While looking at pattern its observed that bottom half is palindrome of top half. Hence we need to calculate only the top half.
Next we see that for every row count,we have pattern like,
row 1 = 1 , n
row 2 = 2 , n -1
row 3 = 1,3, n-2, n
row 4 = 2, 4 , n-3, n-1
.. and so on.
With iteration index as row count and n as input value we can dynamically calculate remaining values very efficiently.
Source-Code
def get_list(bound, alist):
tmp_list = []
for i in xrange(1,bound + 1):
tmp_list.append(star if i in alist else dot)
return tmp_list
star = "*"
dot = " "
n = 20 #How large of BowTie do you want?
m = (n * 2) - 1
#get top half list
th = []
for idx,k in enumerate(xrange(1,n+1)): #run through 1 - n
row = idx + 1
tmplst = []
if row % 2 != 0:
tmplst.append(i for i in xrange(1,row + 1) if i % 2 != 0)
tmplst.append(i for i in xrange(m, m-row, -1) if i % 2 != 0)
else:
tmplst.append(i for i in xrange(1,row + 1) if i % 2 == 0)
tmplst.append(i for i in xrange(m, m-row, -1) if i % 2 == 0)
#append each row value to top half list.
th.append(sorted(set([j for i in tmplst for j in i])))
#create palindrome of top half which is our bottom half
th = th + th[len(th) -2::-1]
#create list of * and blanks
final = [get_list(m, i) for i in th]
#Print BowTie
for i in final:
print ' '.join(i)
Using a stars and spacing and counting variable
counting=1
star_amount=1
space_amount=6
loop_var=7
while loop_var>0:
loop_var-=1
if space_amount==0:
counting*=-1
stars=" * "*star_amount
spaces=" "*space_amount
print(stars+spaces+stars)
star_amount+=counting
space_amount-= counting*2

Categories

Resources