eshangj/stackoverflow_q_and_a_sample huggingface dataset:
Question: My goal. I am using matplotlib slider to plot several series. I want to have hovering labels for each point. Each point corresponds to measurement. So I want to display measurement name to be on these hovering labels. Question. How do I update labels for new series (for slider positions)? If I create new cursor in update function I get several labels for each point. So I need somehow to delete old label first. How do I do this? Description. On first slide I get points with A and B labels. On second slide I should get C and D labels, but I am getting A and B again. My code. import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotlib.widgets import Slider import mplcursors as mplc %matplotlib widget data = {'Name': ['A', 'B', 'C', 'D'], 'x': [1,3,3,2],'y': [4,7,5,1],'color': [1,2,3,2],'size' :[50,40,10,30],'slide': [1,1,2,2]} df=pd.DataFrame.from_dict(data) dff=df.loc[df['slide']==1] z=list(set(df['slide'].to_list())) x = dff['x'].to_list() y = dff['y'].to_list() lbl=dff['Name'].to_list() fig, ax = plt.subplots() ax.clear() points = ax.scatter(x,y,s=100, alpha=0.5) mplc.cursor(ax, hover=True).connect( "add", lambda sel: sel.annotation.set_text(lbl[sel.index])) xmin=min(x) xmax=max(x) ymin=min(y) ymax=max(y) ax.set_ylim([xmin-10,xmax+10]) ax.set_xlim([ymin-10,xmax+10]) axfreq = fig.add_axes([0.15, 0.1, 0.65, 0.03]) plot_slider = Slider( ax=axfreq, label='', valmin=0, valmax=len(z), valinit=1, valstep=1,) def update(val): dff=df.loc[df['slide']==plot_slider.val] x = dff['x'].to_list() y = dff['y'].to_list() lbl=dff['Name'].to_list() points.set_offsets(np.c_[x,y]) plot_slider.on_changed(update) plt.show() 

Answer: I had to (!pip install mplcursors ipympl) before I could run your code. Here is my workaround to get the correct annotations/labels after the slider being updated : sliders = df["slide"].unique() fig, ax = plt.subplots() d = {} for sl in sliders: lbl, x, y = df.loc[ df["slide"].eq(sl), ["Name", "x", "y"]].T.to_numpy() pts = ax.scatter(x, y, s=100) curs = mplc.cursor(pts, hover=True) curs.connect("add", lambda sel, lbl=lbl: sel.annotation.set_text(lbl[sel.index])) d[sl] = {"cursor": curs, "scatter": pts} axfreq = fig.add_axes([0.15, 0.01, 0.73, 0.03]) # << I adjusted this plot_slider = Slider( ax=axfreq, label="", valinit=1, valstep=1, valmin=min(sliders), valmax=max(sliders)) def curscatter(sl, op=0.5): """Display the cur/pts for the requested slider only""" for _sl, inf in d.items(): curs = inf["cursor"]; pts = inf["scatter"] pts.set_alpha(op if _sl == sl else 0) curs.visible = (_sl == sl) def update(curr_sl): curscatter(curr_sl) curscatter(plot_slider.val) # or curscatter(1) plot_slider.on_changed(update) plt.show()       Name x y color size slide     A 1 4 1 50 1   B 3 7 2 40 1   C 3 5 3 10 2   D 2 1 2 30 2
Question: I have an script that checks the position of the mouse every 60 seconds. If the mouse has not moved, it moves it, makes a right click, clicks esc, and sleeps. It is pretty handy to avoid the computer going to sleep. If the mouse has moved, does nothing, goes to sleep and checks again in 60 sec. Now I want to extend it to detect any key pressed. and take it in the same way as the mouse. If a key has been pressed, then just go to sleep. I found the module keyboard, that allows to detect pressed keys. However, it blocks the execution while waiting for a pressed key. Therefore, I would like to find a way to stop "listening" with keyboard after an specified time. That way, instead of sleep, I would use that. If either the mouse is moved or the keyboard is pressed don't do anything. I have not been able to find anything that works for Windows. I hope you can help.

Answer: You can use method #3 of https://stackoverflow.com/a/57644349/9997212:  Method #3: Using the function on_press_key: import keyboard keyboard.on_press_key("p", lambda _: print("You pressed p"))  It needs a callback function. I used _ because the keyboard function returns the keyboard event to that function. Once executed, it will run the function when the key is pressed. You can stop all hooks by running this line: keyboard.unhook_all()   This will allow your program to be event-oriented and will not block your main thread. To listen to all keys instead of a specific one, use keyboard.hook. It works the same way: import keyboard keyboard.hook(lambda event: print(f'You pressed {event.name}'))  The key is to set up a global variable as a boolean. The hook works as an interrumption, therefore, everytime that it is triggered, you activate as True the boolean. After the check that you need you turn it back to False. Something like this: import keyboard try: #the try, finally is used to activate and relase the hooks to the keyboard def handle_key(event): global KeyPressed #the almighty global variable that monitors whether the keyboard was pressed or not. KeyPressed = True # print("KeyPressed is now:", event.name) #in case you want to know what did you pressed. return global KeyPressed #the almighty global variable that monitors whether the keyboard was pressed or not. KeyPressed = False #initialize as False, no key was touched keyboard.hook(lambda event: handle_key(event) ) #this activates the detection of pressed keys. Must end with "keyboard.unhook_all()" if not KeyPressed: #means you have not pressed a key do_something() else: #Then a key was pressed KeyPressed = False #reset the pressed state to False sleep(PAUSE) #wait the specified pause finally: keyboard.unhook_all() #this resets the "keyboard.hook(lambda event: handle_key(event) )" so that no more keys are registered
Question: I am trying to draw an arch-like Cubic Spline using SciPy's Cubic Spline function but at some point is creating a non logical shape between two of the control points. The line in black is what the function is evaluating and in green is what I expect to happen (just as it does between points 4 and 8) This is how I create the image (You can check the code and run it here) from scipy.interpolate import CubicSpline import numpy as np import matplotlib.pyplot as plt x = [-0.0243890844, -0.0188174509, -0.00021640210000000056, 0.0202699043, 0.0239562802] # X values of the coordinates for points 2, 4, 8, 13 and 15 y = [-0.0117638968, 0.00469300617, 0.0177650191, 0.00215831073, -0.0154924048] # Y values of the coordinates for points 2, 4, 8, 13 and 15 cs = CubicSpline(x, y) dsX = np.linspace(x[0], x[len(x)-1], num=1000) plt.plot(dsX, cs(dsX), 'k') plt.plot(x, y, 'mo') plt.show()   Do you know how could I fix this? Or what could be causing this? Is there any kind of option/configuration parameter I am missing?

Answer: Cubic splines are prone to overshooting like this due to the constraint of matching 2nd derivatives. Thus small variations in data may cause large variations in the curve itself, including what you seem to have here. There is no way to "fix" this with CubicSpline. What you could do is to clarify your requirements and select an appropriate interpolant. If you can forgo the C2 requirement and C1 interpolant is OK, you can use pchip or Akima1D, as suggested in comments. If you want smoothing not interpolation, there's make_smoothing_spline (as also suggested in the comments).
Question: I have a pandas dataframe that looks like this: import pandas as pd pd.DataFrame({ 'variable': ['gender','gender', 'age_group', 'age_group'], 'category': ['F','M', 'Young', 'Old'], 'value': [0.6, 0.4, 0.7, 0.3], }) variable category value 0 gender F 0.6 1 gender M 0.4 2 age_group Young 0.7 3 age_group Old 0.3  which represents my population. So in my population I have 60% Females, 70% Young etc. I want to calculate the combinations of gender-age_group and output it in a dataframe that looks like this: pd.DataFrame({ 'gender': ['F', 'F', 'M', 'M'], 'age_group': ['Young', 'Old', 'Young', 'Old'], 'percentage': [0.42, 0.18, 0.28, 0.12] }) gender age_group percentage 0 F Young 0.42 1 F Old 0.18 2 M Young 0.28 3 M Old 0.12  which will show that the Young Females in the population are 42% (which comes from 0.6*0.7), the Old Males are 12% (which comes from 0.4*0.3) etc How could I do that ?

Answer: You can split by variable using groupby and compute the combinations with a cross-merge: from functools import reduce group = df.groupby('variable', sort=False) out = reduce(lambda a,b: pd.merge(a, b, how='cross'), (g.rename(columns={'category': k}) .drop(columns='variable') for k, g in group) ) out['percentage'] = (x:=out.filter(like='value')).prod(axis=1) out = out.drop(columns=list(x))  Output:  gender age_group percentage 0 F Young 0.42 1 F Old 0.18 2 M Young 0.28 3 M Old 0.12  Example with more combinations: # input variable category value 0 gender F 0.60 1 gender M 0.40 2 age_group Young 0.70 3 age_group Old 0.30 4 other a 0.45 5 other b 0.55 # output gender age_group other percentage 0 F Young a 0.189 1 F Young b 0.231 2 F Old a 0.081 3 F Old b 0.099 4 M Young a 0.126 5 M Young b 0.154 6 M Old a 0.054 7 M Old b 0.066
Question: I have this Unicode string: my_string = "₁ᴀa̲a̲̲"  How can index and slice it to make other Unicode strings? If I run print([x for x in my_string]) ['₁', 'ᴀ', 'a', '̲', 'a', '̲', '̲']  when I expected ['₁', 'ᴀ', 'a̲', '̲a̲̲'] this prints my_string[3] '̲'  when I expected a̲̲  I tried t define my_string = u"₁ᴀa̲a̲̲"  but the u is automatically deleted by vscode I need my_string as buffer to compose other strings according to his human-readable index.

Answer: You could use the \X regex and findall from the regex module: import regex out = regex.findall(r'\X', my_string)  Output: ['₁', 'ᴀ', 'a̲', 'a̲̲']
Question: How to find the nouns in a sentence regarding the context? I am using the nltk library as follows: text = 'I bought a vintage car.' text = nltk.word_tokenize(text) result = nltk.pos_tag(text) result = [i for i in result if i[1] == 'NN'] #result = [('vintage', 'NN'), ('car', 'NN')]  The problem with this script is that it considers vintage as a noun, which can be true, but given the context, it is an adjective. How can we achieve this task? Appendix: Using textblob, we get "vintage car" as the noun: !python -m textblob.download_corpora from textblob import TextBlob txt = "I bought a vintage car." blob = TextBlob(txt) print(blob.noun_phrases) #['vintage car'] 

Answer: Using spacy might solve your task. Try this: import spacy nlp = spacy.load("en_core_web_lg") def analyze(text): doc = nlp(text) for token in doc: print(token.text, token.pos_) analyze("I bought a vintage car.") print() analyze("This old wine is a vintage.")  Output I PRON bought VERB a DET vintage ADJ <- correctly identified as adjective car NOUN . PUNCT This DET old ADJ wine NOUN is AUX a DET vintage NOUN <- correctly identified as noun . PUNCT
Question: If I have a dataframe like this:     id col1 col2 idxmax     1 3.0 4.0 col2   2 5.0 5.0 tiebreak   3 6.0 9.0 col 2     In the case of my example dataframe I'd like to return either col1 or col2 based on whichever name wins the tie. Not including the row ID. At the moment the df.idxmax(axis = 1) function just returns the column name of the column with first max value, as per the documentation. However, to ensure elimination of bias, I'd like to turn this into a random tie break but I genuinely have no idea how to do this. Could you please help?

Answer: I like @Timeless' approach with random sampling, the issue is that it will always use the same tie-breaker for different rows that have the same combination of equal maxes. An alternative would be to first stack the data: df['idxmax'] = (df .drop(columns=['id', 'idxmax'], errors='ignore') .stack() .sample(frac=1) .groupby(level=0).idxmax().str[1] )  Alternatively: cols = df.columns.difference(['id', 'idxmax']) m = df[cols].eq(df[cols].max(axis=1), axis=0) df['idxmax'] = (m[m].stack().reset_index(1) .groupby(level=0)['level_1'].sample(n=1) )  Example output:  id col1 col2 idxmax 0 1 3.0 4.0 col2 1 2 5.0 5.0 col2 2 3 6.0 9.0 col2
Question: I have a 2D boolean numpy array, mask: array([[False, False, False, True, True, False, False, False], [ True, True, True, False, True, False, False, False], [False, False, True, False, False, True, False, True], [ True, False, False, False, True, True, False, False]])  mask was generated by: np.random.seed(43210) mask = (np.random.rand(4,8)>0.7)  I visualize mask via: plt.pcolormesh(mask) plt.gca().invert_yaxis() plt.gca().set_aspect('equal')  Result:  I use scipy.ndimage.label to label the features, ie sections of neighbouring True elements in the array. label, num_features = scipy.ndimage.label(mask)  label is then: array([[0, 0, 0, 1, 1, 0, 0, 0], [2, 2, 2, 0, 1, 0, 0, 0], [0, 0, 2, 0, 0, 3, 0, 4], [5, 0, 0, 0, 3, 3, 0, 0]], dtype=int32)  visualization:  However, I would like to have an array where the features are marked by an number showing the size of the feature. I achieve this by: newlabel = np.zeros(label.shape) for i in range(1,num_features+1): # works but very slow newlabel[label==i]=sum((label==i).flatten())  newlabel is then: array([[0., 0., 0., 3., 3., 0., 0., 0.], [4., 4., 4., 0., 3., 0., 0., 0.], [0., 0., 4., 0., 0., 3., 0., 1.], [1., 0., 0., 0., 3., 3., 0., 0.]])  visualization:  This result above (the newlabel array) is correct, this is what I want. The features with only 1 pixel are marked by 1. (blue squares in the visualization). Features with 3 pixels are marked by 3. (green shapes on plot), while the feature with 4 pixels are marked by 4. in newlabel (yellow shape on plot). The problem with this approach is that the for loop takes a long time when mask is big. Testing with a 100 times larger mask: import time np.random.seed(43210) mask = (np.random.rand(40,80)>0.7) t0 = time.time() label, num_features = scipy.ndimage.label(mask) t1 = time.time() newlabel = np.zeros(label.shape) for i in range(1,num_features+1): newlabel[label==i]=sum((label==i).flatten()) t2 = time.time() print(f"Initial labelling takes: {t1-t0} seconds.") print(f"Relabelling by feature size takes: {t2-t1} seconds.") print(f"Relabelling takes {(t2-t1)/(t1-t0)} times as much time as original labelling.")  Output: Initial labelling takes: 0.00052642822265625 seconds. Relabelling by feature size takes: 0.3239290714263916 seconds. Relabelling takes 615.333786231884 times as much time as original labelling.  This makes my solution unviable on real world examples. How can I label the features by their size faster?

Answer: You could use numpy.unique: n, idx, cnt = np.unique(label, return_inverse=True, return_counts=True) n2, idx2 = np.unique(cnt, return_inverse=True) out = np.where(mask, n2[idx2][idx].reshape(mask.shape), 0)  Output: array([[0, 0, 0, 3, 3, 0, 0, 0], [4, 4, 4, 0, 3, 0, 0, 0], [0, 0, 4, 0, 0, 3, 0, 1], [1, 0, 0, 0, 3, 3, 0, 0]])
Question: Is there a way to convert a NxM matrix A where  all values of A are positive integers  to an NxMxL matrix B where  L = 1 + max(A) B[i,j,k] = {1 if k==A[i,j] and 0 otherwise}  using loops I have done the following: B = np.zeros((A.shape[0],A.shape[1],1+np.amax(A))) for i in range(A.shape[0]): for j in range(A.shape[1]): B[i,j,A[i,j]] = 1  the solution ideally avoids any use of for loops and uses only slicing or indexing or numpy functions

Answer: A sample A: In [231]: A = np.array([1,0,3,2,2,4]).reshape(2,3) In [232]: A Out[232]: array([[1, 0, 3], [2, 2, 4]])  Your code and B: In [233]: B = np.zeros((A.shape[0],A.shape[1],1+np.amax(A))) ...: for i in range(A.shape[0]): ...: for j in range(A.shape[1]): ...: B[i,j,A[i,j]] = 1 ...: In [234]: B Out[234]: array([[[0., 1., 0., 0., 0.], [1., 0., 0., 0., 0.], [0., 0., 0., 1., 0.]], [[0., 0., 1., 0., 0.], [0., 0., 1., 0., 0.], [0., 0., 0., 0., 1.]]])  Defining arrays to index B in way that broadcasts with A: In [235]: I,J=np.ix_(np.arange(2),np.arange(3)) In [236]: B[I,J,A] Out[236]: array([[1., 1., 1.], [1., 1., 1.]])  Use that indexing to change all the 1s of B to 20: In [237]: B[I,J,A]=20 In [238]: B Out[238]: array([[[ 0., 20., 0., 0., 0.], [20., 0., 0., 0., 0.], [ 0., 0., 0., 20., 0.]], [[ 0., 0., 20., 0., 0.], [ 0., 0., 20., 0., 0.], [ 0., 0., 0., 0., 20.]]])  the indexes (2,1) and (1,3) pair with (2,3): In [239]: I,J Out[239]: (array([[0], [1]]), array([[0, 1, 2]]))  There's also newer pair of functions that do that same thing. I'm more familiar with the earlier method In [241]: np.take_along_axis(B,A[:,:,None],2) Out[241]: array([[[20.], [20.], [20.]], [[20.], [20.], [20.]]]) In [243]: np.put_along_axis(B,A[:,:,None],1,axis=2) In [244]: B Out[244]: array([[[0., 1., 0., 0., 0.], [1., 0., 0., 0., 0.], [0., 0., 0., 1., 0.]], [[0., 0., 1., 0., 0.], [0., 0., 1., 0., 0.], [0., 0., 0., 0., 1.]]])
Question: I have a .csv file that has this structure: X310.433,Y9.6 X310.54,Y10 X143.52 X144.77 when there is no "X" or "Y" value in a line, I want to take the value from the line above and copy it to the line after that, that is missing the value. For this example copy the Y10 into the next line, and seperate it with a comma. How can i do this with python?

Answer: Without any utility modules you could do this: Let's assume that the file content is: X310.433,Y9.6 Y999 X310.54,Y10 X143.52 X144.77  ...then... lines: list[tuple[str, str]] = [] with open("foo.csv") as foo: for line in map(str.strip, foo): if line: a, *b = line.split(",") if a[0] == "X": if b: lines.append((a, b[0])) else: lines.append((a, lines[-1][1])) else: assert a[0] == "Y" if b: lines.append((b[0], a)) else: lines.append((lines[-1][0], a)) for line in lines: print(",".join(line))  Output: X310.433,Y9.6 X310.433,Y999 X310.54,Y10 X143.52,Y10 X144.77,Y10  Note: If the first line of the file contains either one of X or Y (but not both) this will fail EDIT: More robust version that rewrites the original file: with open("foo.csv", "r+") as foo: lines: list[tuple[str, str]] = [] for line in map(str.strip, foo): if line: a, *b = line.split(",") if a.startswith("X"): y = b[0] if b else lines[-1][1] lines.append((a, y)) elif a.startswith("Y"): x = b[0] if b else lines[-1][0] lines.append((x, a)) foo.seek(0) for line in lines: print(",".join(line), file=foo) foo.truncate()
Question: I need to implement a function that takes coordinates of any number of points as input data and return True or False depending on whether these points lie on the same line or not. I use Python to solve this problem and now I have the following implementation: def are_colinear(points, tolerance): # variable "points" is a list of lists with points coordinates for i in range(2, len(points)): if (points[i][0] - points[i-2][0])/(points[i-1][0] - points[i-2][0]) - (points[i][1] - points[i-2][1])/(points[i-1][1] - points[i-2][1]) < tolerance and \ (points[i][1] - points[i-2][1])/(points[i-1][1] - points[i-2][1]) - (points[i][2] - points[i-2][2])/(points[i-1][2] - points[i-2][2]) < tolerance: continue else: return False return True  This method is based on the equation of a line passing through two points:  The weakness of this approach is that it raises an error if you want to check points belonging to the same plane (one of three coordinates always equals to zero in this case and one of denominators is zero because of this). I need a better implementation. Thank you in advance!

Answer: Take any one of your coordinates, take it to be your new origin, translating all coordinates accordingly. Now, treat each coordinate as a position vector. Normalize each vector. Now, if any two vectors are parallel, their dot product is 1. In fact, they are the same vector. If two vectors are antiparallel, their dot product is -1 and one vector is the negation of the other. When you expand it all out, you'll find that you don't need to do any divisions, can avoid any square roots, and don't have special edge cases to handle. 1 ?= abs(dot(norm(u), norm(v)) = abs(dot(u, v) / (mag(u) * mag(v))) = dot(u, v)^2 / (mag(u) * mag(v))^2 1 = (ux*vx + uy*vy + uz*vz)^2 / (sqrt(ux^2 + uv^2 + uz^2) * sqrt(vx^2 + vy^2 + vz^2))^2 1 = (ux*vx + uy*vy + uz*vz)^2 / ((ux^2 + uv^2 + uz^2) * (vx^2 + vy^2 + vz^2)) (ux^2 + uv^2 + uz^2) * (vx^2 + vy^2 + vz^2) = (ux*vx + uy*vy + uz*vz)^2  This is pretty easy to code up: def are_parallel(points): points = set(points) # dedupe if len(points) < 3: return True xo, yo, zo = points.pop() # extract origin translated_points = [(x-xo, y-yo, z-zo) for x, y, z in points] ux, uy, uz = translated_points[0] # first/reference vector u_mag_sqr = ux**2 + uy**2 + uz**2 for vx, vy, vz in translated_points[1:]: # rest of vectors v_mag_sqr = vx**2 + vy**2 + vz**2 uv_dot_sqr = (ux*vx + uy*vy + uz*vz)**2 if u_mag_sqr * v_mag_sqr != uv_dot_sqr: return False return True  Again, its worth emphasizing that this avoids division, square roots, or anything that would introduce floating-point comparison to what could otherwise be integer coordinates, its faster because its just multiplications and additions, and it doesn't have weird edge cases around specific classes of coordinates.
Question: Does it make sense to import from typing inside a TYPE_CHECKING block? Is this good/bad or does it even matter? from __future__ import annotations from typing import TYPE_CHECKING, Protocol, runtime_checkable if TYPE_CHECKING: from typing import Any, Callable, Generator 

Answer: Since typing is a built-in module and you are already importing it to use TYPE_CHECKING anyway, the answer is no, it does not make much sense. Also, it will only work if all of the usages of imported classes are within quotes (for lazy evaluation). Otherwise you will get a NameError when the code runs: from typing import TYPE_CHECKING if TYPE_CHECKING: from typing import List li: List = []  results with NameError: name 'List' is not defined  as opposed to from typing import TYPE_CHECKING if TYPE_CHECKING: from typing import List li: 'List' = []  which works.
Question: In Python 3, I have a list (my_array) that contains an instance of the Demo class with a certain attribute set on that instance. In my case, the attribute is value: int = 4. Given an instance of the Demo class, how can I determine if that instance already exists in my_array with the same properties. Here's a MCRE of my issue: from typing import List class Demo: def __init__(self, value: int): self.value = value my_array: List[Demo] = [Demo(4)] print(Demo(4) in my_array) # prints False  However, Demo(4) clearly already exists in the list, despite that it prints False. I looked through the Similar Questions, but they were unrelated. How can I check if that already exists in the list?

Answer: You need to add an equality function to Demo:  def __eq__(self, other): return isinstance(other, Demo) and self.value == other.value  P.S, since Python 3.9 you don't need to import List and just use: my_array: list[Demo] = [Demo(4)]