How can I print single rows of data from pandas dataframe onto a pygame screen? [duplicate] - pandas

I'm trying to display a basic SQLite database as a table in pygame. It holds the players username and score. The code I have now displays it but it doesn't aligne nicely. The code:
def leader_board():
i = 35
messg = font_style.render(f'PLAYER SCORE', True, yellow)
dis.blit(messg, [dis_width / 5, (700 / 4) + 5])
cur.execute('SELECT * FROM snake_score ORDER BY score desc LIMIT 10')
rows = cur.fetchall()
for row in rows:
mesgg = font_style.render('{:>3} {:30}'.format(row[0], row[1]), True, yellow)
dis.blit(mesgg, [dis_width / 5, (700 / 4) + i + 5])
i += 35
This is the result that I get from it:
I'd like the numbers to be all aligned with the end of the word 'score'. Any help would be appreciated because I have tried some things and none seemed to work.

Either use a monospace font or render the text of each column separately:
def leader_board():
i = 35
column_space = 400
head1 = font_style.render(f'PLAYER', True, yellow)
head2 = font_style.render(f'SCORE', True, yellow)
dis.blit(head1, [dis_width / 5, (700 / 4) + 5])
dis.blit(head2, [dis_width / 5 + column_space, (700 / 4) + 5])
cur.execute('SELECT * FROM snake_score ORDER BY score desc LIMIT 10')
rows = cur.fetchall()
for row in rows:
column1 = font_style.render('{:>3}'.format(row[0]), True, yellow)
column2 = font_style.render('{:30}'.format(row[1]), True, yellow)
dis.blit(column1, [dis_width / 5, (700 / 4) + i + 5])
dis.blit(column2, [dis_width / 5 + column_space, (700 / 4) + i + 5])
i += 35

Related

Algorithm to define a 2d grid

Suppose a grid is defined by a set of grid parameters: its origin (x0, y0), an angel between one side and x axis, and increments and - please see the figure below.
There are scattered points with known coordinates on the grid but they don’t exactly fall on grid intersections. Is there an algorithm to find a set of grid parameters to define the grid so that the points are best fit to grid intersections?
Suppose the known coordinates are:
(2 , 5.464), (3.732, 6.464), (5.464, 7.464)
(3 , 3.732), (4.732, 4.732), (6.464, 5.732)
(4 , 2 ), (5.732, 3 ), (7.464, 4 ).
I expect the algorithm to find the origin (4, 2), the angle 30 degree, and the increments both 2.
You can solve the problem by finding a matrix that transforms points from positions (0, 0), (0, 1), ... (2, 2) onto the given points.
Although the grid has only 5 degrees of freedom (position of the origin + angle + scale), it is easier to define the transformation using 2x3 matrix A, because the problem can be made linear in this case.
Let a point with index (x0, y0) to be transformed into point (x0', y0') on the grid, for example (0, 0) -> (2, 5.464) and let a_ij be coefficients of matrix A. Then this pair of points results in 2 equations:
a_00 * x0 + a_01 * y0 + a_02 = x0'
a_10 * x0 + a_11 * y0 + a_12 = y0'
The unknowns are a_ij, so these equations can be written in form
a_00 * x0 + a_01 * y0 + a_02 + a_10 * 0 + a_11 * 0 + a_12 * 0 = x0'
a_00 * 0 + a_01 * 0 + a_02 * 0 + a_10 * x0 + a_11 * y0 + a_12 = y0'
or in matrix form
K0 * (a_00, a_01, a_02, a_10, a_11, a_12)^T = (x0', y0')^T
where
K0 = (
x0, y0, 1, 0, 0, 0
0, 0, 0, x0, y0, 1
)
These equations for each pair of points can be combined in a single equation
K * (a_00, a_01, a_02, a_10, a_11, a_12)^T = (x0', y0', x1', y1', ..., xn', yn')^T
or K * a = b
where
K = (
x0, y0, 1, 0, 0, 0
0, 0, 0, x0, y0, 1
x1, y1, 1, 0, 0, 0
0, 0, 0, x1, y1, 1
...
xn, yn, 1, 0, 0, 0
0, 0, 0, xn, yn, 1
)
and (xi, yi), (xi', yi') are pairs of corresponding points
This can be solved as a non-homogeneous system of linear equations. In this case the solution will minimize sum of squares of distances from each point to nearest grid intersection. This transform can be also considered to maximize overall likelihood given the assumption that points are shifted from grid intersections with normally distributed noise.
a = (K^T * K)^-1 * K^T * b
This algorithm can be easily implemented if there is a linear algebra library is available. Below is an example in Python:
import numpy as np
n_points = 9
aligned_points = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
grid_points = [(2, 5.464), (3.732, 6.464), (5.464, 7.464), (3, 3.732), (4.732, 4.732), (6.464, 5.732), (4, 2), (5.732, 3), (7.464, 4)]
K = np.zeros((n_points * 2, 6))
b = np.zeros(n_points * 2)
for i in range(n_points):
K[i * 2, 0] = aligned_points[i, 0]
K[i * 2, 1] = aligned_points[i, 1]
K[i * 2, 2] = 1
K[i * 2 + 1, 3] = aligned_points[i, 0]
K[i * 2 + 1, 4] = aligned_points[i, 1]
K[i * 2 + 1, 5] = 1
b[i * 2] = grid_points[i, 0]
b[i * 2 + 1] = grid_points[i, 1]
# operator '#' is matrix multiplication
a = np.linalg.inv(np.transpose(K) # K) # np.transpose(K) # b
A = a.reshape(2, 3)
print(A)
[[ 1. 1.732 2. ]
[-1.732 1. 5.464]]
Then the parameters can be extracted from this matrix:
theta = math.degrees(math.atan2(A[1, 0], A[0, 0]))
scale_x = math.sqrt(A[1, 0] ** 2 + A[0, 0] ** 2)
scale_y = math.sqrt(A[1, 1] ** 2 + A[0, 1] ** 2)
origin_x = A[0, 2]
origin_y = A[1, 2]
theta = -59.99927221917264
scale_x = 1.99995599951599
scale_y = 1.9999559995159895
origin_x = 1.9999999999999993
origin_y = 5.464
However there remains a minor issue: matrix A corresponds to an affine transform. This means that grid axes are not guaranteed to be perpendicular. If this is a problem, then the first two columns of the matrix can be modified in a such way that the transform preserves angles.
Update: I fixed the mistakes and resolved sign ambiguities, so now this algorithm produces the expected result. However it should be tested to see if all cases are handled correctly.
Here is another attempt to solve this problem. The idea is to decompose transformation into non-uniform scaling matrix and rotation matrix A = R * S and then solve for coefficients sx, sy, r1, r2 of these matrices given restriction that r1^2 + r2^2 = 1. The minimization problem is described here: How to find a transformation (non-uniform scaling and similarity) that maps one set of points to another?
def shift_points(points):
n_points = len(points)
shift = tuple(sum(coords) / n_points for coords in zip(*points))
shifted_points = [(point[0] - shift[0], point[1] - shift[1]) for point in points]
return shifted_points, shift
n_points = 9
aligned_points = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
grid_points = [(2, 5.464), (3.732, 6.464), (5.464, 7.464), (3, 3.732), (4.732, 4.732), (6.464, 5.732), (4, 2), (5.732, 3), (7.464, 4)]
aligned_points, aligned_shift = shift_points(aligned_points)
grid_points, grid_shift = shift_points(grid_points)
c1, c2 = 0, 0
b11, b12, b21, b22 = 0, 0, 0, 0
for i in range(n_points):
c1 += aligned_points[i][0] ** 2
c2 += aligned_points[i][0] ** 2
b11 -= 2 * aligned_points[i][0] * grid_points[i][0]
b12 -= 2 * aligned_points[i][1] * grid_points[i][0]
b21 -= 2 * aligned_points[i][0] * grid_points[i][1]
b22 -= 2 * aligned_points[i][1] * grid_points[i][1]
k = (b11 ** 2 * c2 + b22 ** 2 * c1 - b21 ** 2 * c2 - b12 ** 2 * c1) / \
(b21 * b11 * c2 - b12 * b22 * c1)
# r1_sqr and r2_sqr might need to be swapped
r1_sqr = 2 / (k ** 2 + 4 + k * math.sqrt(k ** 2 + 4))
r2_sqr = 2 / (k ** 2 + 4 - k * math.sqrt(k ** 2 + 4))
for sign1, sign2 in [(1, 1), (-1, 1), (1, -1), (-1, -1)]:
r1 = sign1 * math.sqrt(r1_sqr)
r2 = sign2 * math.sqrt(r2_sqr)
scale_x = -b11 / (2 * c1) * r1 - b21 / (2 * c1) * r2
scale_y = b12 / (2 * c2) * r2 - b22 / (2 * c2) * r1
if scale_x >= 0 and scale_y >= 0:
break
theta = math.degrees(math.atan2(r2, r1))
There might be ambiguities in choosing r1_sqr and r2_sqr. Origin point can be estimated from aligned_shift and grid_shift, but I didn't implement it yet.
theta = -59.99927221917264
scale_x = 1.9999559995159895
scale_y = 1.9999559995159895

geom_violin using the weight aesthetic unexpectedly drop levels

library(tidyverse)
set.seed(12345)
dat <- data.frame(year = c(rep(1990, 100), rep(1991, 100), rep(1992, 100)),
fish_length = sample(x = seq(from = 10, 131, by = 0.1), 300, replace = F),
nb_caught = sample(x = seq(from = 1, 200, by = 0.1), 300, replace = T),
stringsAsFactors = F) %>%
mutate(age = ifelse(fish_length < 20, 1,
ifelse(fish_length >= 20 & fish_length < 100, 2,
ifelse(fish_length >= 100 & fish_length < 130, 3, 4)))) %>%
arrange(year, fish_length)
head(dat)
year fish_length nb_caught age
1 1990 10.1 45.2 1
2 1990 10.7 170.0 1
3 1990 10.9 62.0 1
4 1990 12.1 136.0 1
5 1990 14.1 80.8 1
6 1990 15.0 188.9 1
dat %>% group_by(year) %>% summarise(ages = n_distinct(age)) # Only 1992 has age 4 fish
# A tibble: 3 x 2
year ages
<dbl> <int>
1 1990 3
2 1991 3
3 1992 4
dat %>% filter(age == 4) # only 1 row for age 4
year fish_length nb_caught age
1 1992 130.8 89.2 4
Here:
year = year of sampling
fish_length = length of the fish in cm
nb_caught = number of fish caught following the use of an age-length key, hence explaining the presence of decimals
age = age of the fish
graph1: geom_violin not using the weight aesthetic.
Here, I got to copy each line of dat according to the value found in nb_caught.
dim(dat) # 300 rows
dat_graph1 <- dat[rep(1:nrow(dat), floor(dat$nb_caught)), ]
dim(dat_graph1) # 30932 rows
dat_graph1$nb_caught <- NULL # useless now
sum(dat$nb_caught) - nrow(dat_graph1) # 128.2 rows lost here
Since I have decimal values of nb_caught, I took the integer value to create dat_graph1. I lost 128.2 "rows" in the process.
Now for the graph:
dat_tile <- data.frame(year = sort(unique(dat$year))[sort(unique(dat$year)) %% 2 == 0])
# for the figure's background
graph1 <- ggplot(data = dat_graph1,
aes(x = as.factor(year), y = fish_length, fill = as.factor(age),
color = as.factor(age), .drop = F)) +
geom_tile(data = dat_tile, aes(x = factor(year), y = 1, height = Inf, width = 1),
fill = "grey80", inherit.aes = F) +
geom_violin(draw_quantiles = c(0.05, 0.5, 0.95), color = "black",
scale = "width", position = "dodge") +
scale_x_discrete(expand = c(0,0)) +
labs(x = "Year", y = "Fish length", fill = "Age", color = "Age", title = "graph1") +
scale_fill_brewer(palette = "Paired", drop = F) + # drop = F for not losing levels
scale_color_brewer(palette = "Paired", drop = F) + # drop = F for not losing levels
scale_y_continuous(expand = expand_scale(mult = 0.01)) +
theme_bw()
graph1
graph1
Note here that I have a flat bar for age 4 in year 1992.
dat_graph1 %>% filter(year == 1992, age == 4) %>% pull(fish_length) %>% unique
[1] 130.8
That is because I only have one length for that particular year-age combination.
graph2: geom_violin using the weight aesthetic.
Now, instead of copying each row of dat by the value of number_caught, let's use the weight aesthetic.
Let's calculate the weight wt that each line of dat will have in the calculation of the density curve of each year-age combinations.
dat_graph2 <- dat %>%
group_by(year, age) %>%
mutate(wt = nb_caught / sum(nb_caught)) %>%
as.data.frame()
head(dat_graph2)
year fish_length nb_caught age wt
1 1990 10.1 45.2 1 0.03573123
2 1990 10.7 170.0 1 0.13438735
3 1990 10.9 62.0 1 0.04901186
4 1990 12.1 136.0 1 0.10750988
5 1990 14.1 80.8 1 0.06387352
6 1990 15.0 188.9 1 0.14932806
graph2 <- ggplot(data = dat_graph2,
aes(x = as.factor(year), y = fish_length, fill = as.factor(age),
color = as.factor(age), .drop = F)) +
geom_tile(data = dat_tile, aes(x = factor(year), y = 1, height = Inf, width = 1),
fill = "grey80", inherit.aes = F) +
geom_violin(aes(weight = wt), draw_quantiles = c(0.05, 0.5, 0.95), color = "black",
scale = "width", position = "dodge") +
scale_x_discrete(expand = c(0,0)) +
labs(x = "Year", y = "Fish length", fill = "Age", color = "Age", title = "graph2") +
scale_fill_brewer(palette = "Paired", drop = F) + # drop = F for not losing levels
scale_color_brewer(palette = "Paired", drop = F) + # drop = F for not losing levels
scale_y_continuous(expand = expand_scale(mult = 0.01)) +
theme_bw()
graph2
dat_graph2 %>% filter(year == 1992, age == 4)
year fish_length nb_caught age wt
1 1992 130.8 89.2 4 1
graph2
Note here that the flat bar for age 4 in year 1992 seen on graph1 has been dropped here even though the line exists in dat_graph2.
My questions
Why is the age 4 in 1992 level dropped when using the weight aesthetic? How can I overcome this?
Why are the two graphs not visually alike even though they used the same data?
Thanks in advance for your help!
1.
Problem 1 is not related to using the weight aesthetic. You can check this by dropping the weight aesthetic in the code for your second graph. The problem is, that the algorithm for computing the density fails, when there are too less observations.
That is the reason, why group 4 shows up in graph 1 with the expanded dataset (grpah 1). Here you increase the number of observations by replicating the number of obs.
Unfortunately, geom_violin gives no warning in your specific case. However, if you filter dat_graph2 for age == 4 geom_violin gives you the warning
Warning message:
Computation failed in `stat_ydensity()`:
replacement has 1 row, data has 0
geom_density is much clearer on this issue, giving a warning, that groups with less than two obs have been dropped.
Unfortunately, I have no solution to overcome this, besides working with the expanded dataset.
2.
Concerning problem 2 I have no convincing answer except that I guess that this is related to the details of the kernel density estimator used by geom_violin, geom_density, ... and perhaps also somehow related to the number of data points.

sum numpy array at given indices

I want to add the values of a vector:
a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='d')
to the values of another vector:
c = np.array([10, 10, 10], dtype='d')
at position given by another array (of the same size of a, with values 0 <= b[i] < len(c))
b = np.array([2, 0, 1, 0, 2, 0, 1, 1, 0, 2], dtype='int32')
This is very simple to write in pseudo code:
for I in range(b.shape[0]):
J = b[I]
c[J] += a[I]
Something like this, but vectorized (length of c is some hundreds in real case).
c[0] += np.sum(a[b==0]) # 27 (10 + 1 + 3 + 5 + 8)
c[1] += np.sum(a[b==1]) # 25 (10 + 2 + 6 + 7)
c[2] += np.sum(a[b==2]) # 23 (10 + 0 + 4 + 9)
My initial guess was:
c[b] += a
but only last values of a are summed.
You can use np.bincount to get ID based weighted summations and then add with c, like so -
np.bincount(b,a) + c

Monte Carlo Simulation Method with VBA

I have a code which generates a Probability distribution for the total profit of price using the Monte Carlo Simulation Method.
How does the data in column F and G , display the cumulative distribution of profit ?
I understand that it will compute the cumulative frequency using a range of values which is given
given by Int(Iteration / 20 * i).
but I don't see how it is related to the Probability that Profit >= X in column F.
ie.
if I choose 100 for my iterations ,
then
TP(Int(Iteration / 20 * i))
= TP(Int(100 / 20 * i))
= TP(Int(5 * i))
and so it would only display,
TP(5), TP(10) , TP(15) and TP(20)
if i = 5
TP(Int(Iteration / 20 * i))
= TP(Int(100 / 20 * i))
= TP(Int(5 * 5))
and i get TP(25) which is out of the range.
this is the part of the code I'm confused about :
For i = 1 To 20
Cells(i + 3, 6) = 1 - (0.05 * i)
Cells(i + 3, 7) = TP(Int(Iteration / 20 * i))
Cells(i + 3, 14) = Iteration / 20 * i
Next i
http://www.anthony-vba.kefra.com/vba/vba12.htm
From the code and the data you are providing, there shouldn't be any out of range:
ReDim TP(Iteration) As Double 'Is defined as function of the number of iterations (100 here)
Cells(i + 3, 6) = 1 - (0.05 * i) 'Writes to the F column until row 8
Cells(i + 3, 7) = TP(Int(Iteration / 20 * i)) 'Writes to the G column until row 8
'The maximum value for TP(Int(Iteration / 20 * i)) is 25, below 100
'Actually, this array should be dimensioned in a more direct way like ReDim TP(Int(Iteration / 20 * i)) As Double
If you get an out of bounds error is because the TP array is not dimensioned as it should be: either because you missed the line above (ReDim TP(Iteration) As Double), or because you didn't assign the right value to the variable Iteration (= 100) before doing the aforementioned redimensioning.

Finding a point on a diagonal line when i have the start point and end point of the Line

Hi am looking for some help
I have a Diagonal line drawn on a picture box on my forum and i need to know if the user has clicked the line
I have the Start point and End Point of the Line and the mouse x,y location
So i basically need to find out if the x,y of the mouse is on the line.
can anyone help?
Thanks
Example: Line Start point (A) is (0, 0), END point (B) is (10, 5).
Slope of line is therefore:
m(slope) = (y2 - y1) / (x2 - x1)
= (5 - 0) / (10 - 0)
= 5 / 10
= 0.5
To check if your point(x,y) (C) is on the line it must have the same slope from A->C and C->B. so do the same calculation again. Say point is (4, 2)
m(AC) = (2 - 0) / (4 - 0)
= 2 / 4
= 0.5
m(CB) = (5 - 2) / (10 - 4)
= 3 / 6
= 0.5
Therefore this point would be on line AB.
If point was (20, 10)
m(AC) = (10 - 0) / (20 - 0)
= 10 / 20
= 0.5
However:
m(CB) = (5 - 10) / (10 - 20)
= -5 / -10
= -0.5
Similarly if point was (2, 2)
m(AC) = (2 - 0) / (2 - 0)
= 2 / 2
= 1
m(CB) = (5 - 2) / (10 - 2)
= 3 / 8
= 0.375
So for a point to be on a line m(AB) == m(AC) == m(CB)
You may have a bit of work arounds to perform as you may not be able to get decimal values, and your line may be more than one pixel in width, but these basic principles should see you through.
Given two points, (2,4) and (-1,-2) determine the slope intercept form of the line.
1. Determine the slope
y1-y2 4-(-2) 6
----- = ------= --- = 2 = M
x1-x2 2-(-1) 3
2. To slope intercept form using one of the original points and slope from above.
(y - y1) = m(x - x1)
(y - 4) = 2(x - 2)
y - 4 = 2x - 4
y = 2x + 0 (0 is y intercept)
y = 2x (y = 2x + 0) is in slope intercept form
3. To determine if a point lies on the line, plug and chug with the new point.
new point (1,2) does y = 2x? 2 = 2(1) = true so (1,2) is on the line.
new point (2,2) does y = 2x? 2 = 2(2) = false so (2,2) is not on the line.
In your original problem you said line, but I think you might mean line segment. If you mean the latter you will also need to verify that the new x and y are within the bounds of the given segment.
The code will look something like this
Dim pta As Point = New Point(2, 4)
Dim ptb As Point = New Point(-1, -2)
Dim M As Double
If pta.X - ptb.X <> 0 Then
M = (pta.Y - ptb.Y) / (pta.X - ptb.X)
End If
'(y - pta.y) = M(x - pta.x)
'y - pta.y = Mx - m(pta.x)
'y = Mx - M(pta.x) + pta.y
Dim yIntercept As Double = (-M * pta.X) + pta.Y
Dim ptN1 As Point = New Point(1, 2)
Dim ptN2 As Point = New Point(2, 2)
If ptN1.Y = (M * (ptN1.X)) + yIntercept Then
Stop
Else
Stop
End If
If ptN2.Y = (M * (ptN2.X)) + yIntercept Then
Stop
Else
Stop
End If