I have a data frame and want to update specific cells in a column based on a condition on another column.
ID Name Metric Unit Value
2 1 K2 M1 msecond 1
3 1 K2 M2 NaN 10
4 2 K2 M1 usecond 500
5 2 K2 M2 NaN 8
The condition is, if Unit string is msecond, then multiply the corresponding value in Value column by 1000 and store it in the same place. Considering a constant step for row iteration (two-by-two), the following code is not correct
i = 0
while i < len(df_group):
x = df.iloc[i].at["Unit"]
if x == 'msecond':
df.iloc[i].at["Value"] = df.iloc[i].at["Value"] * 1000
i += 2
However, the output is the same as before modifications. How can I fix that? Also what are the alternatives for better coding instead of that while loop?
A much simpler (and more efficient) form would be to use loc:
df.loc[df['Unit'] == 'msecond', 'Value'] *= 100
If you consider it essentially to only update a specific step of indexes:
step = 2
start = 0
df.loc[df['Unit'].eq('msecond') & (df.index % step == start), 'Value'] *= 100
I have a table consisting of 3 different categories : MainLand, Island, City ; each one has 2 different possible values where one is assigned to them depending on 'weight'. If 'Weight' <= 2kg then our output, 'Cost', is eg. 1.2 (for Mainland or 1.3 for island etc). If 'weight' >2kg , we need to round it to the nearest integer , then calculate 0.3(for mainland or 0.9 for island etc) times the extra integers above 2kg. The cost then will be the original value for the first 2kg and then add up the decimal of each area times the extra integers . I tried creating my own function to select 3 cells and do the calculation since it seemed too complex for linear functions given from excell.
But I always get an error...
Note all variable values are from user-selected cells and the Location value simply checks which text there is inside the cell to assign the proper numbers for calculation.
Thats what I have so far... Any tips?
Function TotalCost(ByVal tmx As Integer, ByVal weight As Double, _
ByVal Location As Text)
Dim b As Integer
Dim c As Integer
Dim d As Integer
d = 0
c = 0
f = 0
If Location Like "Mainland" And weight <= 2 Then
TotalCost = 1.2
ElseIf Location Like "Mainland" And weight > 2 Then
weight = Round(weight, 0)
c = weight - 2
Do While c > 0
c = c - 1
d = d + 1
Loop
TotalCost = tmx * ((d * 9.55) + 1.2)
ElseIf Location Like "City" And weight <= 2 Then
TotalCost = 1.1
ElseIf Location Like "City" And weight > 2 Then
weight = Round(weight, 0)
c = weight - 2
Do While c > 0
c = c - 1
d = d + 1
Loop
TotalCost= tmx * ((d * 0.55) + 1.1)
ElseIf Location Like "Island" And weight <= 2 Then
TotalCost = 1.3
ElseIf Location Like "Island" And weight > 2 Then
weight = Round(weight, 0)
c = weight - 2
Do While c > 0
c = c - 1
d = d + 1
Loop
TotalCost= tmx * ((d * 0.7) + 1.3)
End If
End Function
Something more like this might be better:
Function TotalCost(ByVal tmx As Integer, ByVal weight As Double, _
ByVal Location As String)
Dim base As Double, mult As Double, tot As Double, wtExtra As Double
Select Case Location
Case "Mainland"
base = 1.2
mult = 9.55
Case "City"
base = 1.1
mult = 0.55
Case "Island"
base = 1.3
mult = 0.7
Case Else
TotalCost = "?Location?"
Exit Function
End Select
If weight > 2 Then
'round up to nearest kg and subtract 2
wtExtra = Application.Ceiling(weight, 1) - 2
TotalCost = tmx * ((wtExtra * mult) + base)
Else
TotalCost = base
End If
End Function
You can do your calculation with a relatively simple formula but it needs a little preparation, some of which is the same you will need for the UDF as well. Here is the formula. I'll explain it in detail below.
=VALUE(INDEX(Rates,1,MATCH($F$2,$B$1:$D$1))+(INDEX(Rates,2,MATCH($F$2,$B$1:$D$1))*(-INT($G$2/-2)-1)))*INT(MAX($H$2,1))
First, the setup.
I placed the table you published in your question into a range A1:D3.
I created a named range for the numbers, B1:D3, and called it Rates
Then I created a Validation drop-down in F2 which refers to the range B1:D1 ("City", "Mainland" "Islands")
I marked cell G2 for entering the Weight
And H2 for entering the quantity of parcels.
Next the preparations.
[G6] =MATCH(F2,B1:D1) returns 1, 2 or 3 depending upon what is selected in F2
[G7] =(-INT(G2/-2)-1) returns the number of surcharges for extra weight, like 0 for anything up to 2(kg), 1 for 2.1 to 4.0, 2 for 2.1 to 6.0 etc.
[G5] =INT(MAX(H2,1))
All of these formulas must be tested individually by checking their results while F2:H2 are being changed. (I did that.) That leads to the basic formula.
=INDEX(Rates,1,G6)+(INDEX(Rates,2,G6)*G7)
and, because it's a string,
=VALUE(INDEX(Rates,1,G6)+(INDEX(Rates,2,G6)*G7))
and, to multiply with the number of parcels,
=VALUE(INDEX(Rates,1,G6)+(INDEX(Rates,2,G6)*G7))*G5
Now all that remains to be done is to replace G5, G6 and G7 in the above with the formulas in G5, G6 and G7. Then add $ signs to enable copying of the formula and you get the result first above offered.
I have the equation: sqrt(2)*cos(xy) = (z/sqrt(2)) + sin(z) - cos(z)
with following interval
-1 <= x <= 1 and dx = 0.1
0 <= y <= 1.5 and dx = 0.05
that I need to plot the 3D surface of on excel.
I can't simplify the equation interms of z so how can I calculate the possible values in the matrix form for the given x and y values?
I am following this tutorial: https://www.youtube.com/watch?v=jUoo_7KQfO0 but I don't know how to write the above equation in terms of z.
First of all your number of values of x/y looks different, x has 20 values, while y has 30
I think it should be
-1 <= x <= 1 and dx = 0.1
0 <= y <= 1 and dx = 0.05
Or
-1 <= x <= 2 and dx = 0.1
0 <= y <= 1.5 and dx = 0.05
Then about z, you can find it in excel using Goal Seek
with formulae
In above screenshot using Goal Seek you have to find value of (z/sqrt(2)) + sin(z) - cos(z) (column F) where it is equal to value of sqrt(2)*cos(xy) (column E) by changing the values of Z(column C)
As an example: For first value you would enter like below
After you have generated all z you can select all the data of x, y and z and insert the 3d surface graph.
I want to extract coordinates of theses icon ,How can I do this using python
Any help will be appreciated enter image description here
Thank you
Does it help you?
def get_pos_x(col):
return (col - 1) * 51 + 1
def get_pos_y(row):
return 4 + (row - 1) * 56 + (row - 1) * 11 + 1
icon = (51, 56) # width * height
col = 2
row = 2
print(get_pos_x(col))
print(get_pos_y(row))
Each icon needs on your screen 51 pixels in width and 56 pixels in height. In addition, consider the distance to the first row of 4 pixels and between the rows of 11 pixels. I've added a pixel to x and y so that you can get to the next icon.
Background:
I have a very large excel file in terms of row number.
I have a column, say Column A, that is composed of either formulas or numbers or string.
I want to 'copy' Column A to Column C and D:
For a row i:
if 'Bi' is not 0:
then for column C and D:
'Ci' or 'Di' = 'Bi'
else:
if 'Ai' is not a formula:
then for column C and D:
'Ci' or 'Di' = 'Ai'
else:
then for column C and D:
formula in 'Ai' should be copied to 'Ci' or 'Di' but adjusted. E.g. '=A1+A2' should be translated to '=C1+C2' or '=D1+D2'
I have half-coded the following sudo-code and hope someone can help me move toward the direction of finishing it.
import pandas as pd
import numpy as np
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
# add a simple formula
ws["A1"] = 2
ws["A2"] = 3
ws["A3"] = "=1+SUM(A1:A2)"
ws["B1"] = 3
ws["B2"] = 0
ws["B3"] = "=1+SUM(A1:A2)"
wb.save("experiment_openpyxl.xlsx")
data_df = np.array([[2,3],[3,0],['=1+SUM(A1:A2)',0]])
df = pd.DataFrame(data=data_df)
print(df)
print(len(df.index))
print(len(df.columns))
column_num_A = 0;
column_num_B = 1;
column_num_C = 2;
column_num_D = 3;
for i in range(0,len(df.index)):
if df.loc[i,column_num_B] != 0:
for j in list[column_num_C,column_num_D]:
df.loc[i,j] = df.loc[i,column_num_B]
else:
#if df.loc[i,column_num_A] is not a formula:
#for j in list[column_num_C,column_num_D]:
#df.loc[i,j] = df.loc[i,column_num_A]
#else:
#for j in list[column_num_C,column_num_D]:
#df.loc[i,j] = <copy the formula in df.loc[i,column_num_A] but translate A1 etc. to C1 or D1 based on j>
Expected output:
df original:
0 1
0 2 3
1 3 0
2 =1+SUM(A1:A2) 0
df post-processed:
0 1 2 3
0 2 3 3 3
1 3 0 3 3
2 =1+SUM(A1:A2) 0 =1+SUM(C1:C2) =1+SUM(D1:D2)