eshangj/stackoverflow_q_and_a_sample huggingface dataset:
Question: Windows, vscode, Python 3.11.4-64bit import torch import torchaudio print(torch.__version__) print(torchaudio.__version__) print(torchaudio._extension._FFMPEG_INITIALIZED)  2.0.1+cu117 2.0.2+cu117 False  and i try torchaudio._extension._init_ffmpeg()  Traceback (most recent call last): File "C:\Users\USER\AppData\Local\Programs\Python\Python311\Lib\site-packages\torchaudio\_extension\utils.py", line 85, in _init_ffmpeg _load_lib("libtorchaudio_ffmpeg") File "C:\Users\USER\AppData\Local\Programs\Python\Python311\Lib\site-packages\torchaudio\_extension\utils.py", line 61, in _load_lib torch.ops.load_library(path) File "C:\Users\USER\AppData\Local\Programs\Python\Python311\Lib\site-packages\torch\_ops.py", line 643, in load_library ctypes.CDLL(path) File "C:\Users\USER\AppData\Local\Programs\Python\Python311\Lib\ctypes\__init__.py", line 376, in __init__ self._handle = _dlopen(self._name, mode) ^^^^^^^^^^^^^^^^^^^^^^^^^ FileNotFoundError: Could not find module 'C:\Users\USER\AppData\Local\Programs\Python\Python311\Lib\site-packages\torchaudio\lib\libtorchaudio_ffmpeg.pyd' (or one of its dependencies). Try using the full path with constructor syntax. The above exception was the direct cause of the following exception: Traceback (most recent call last): File "c:\Users\USER\Desktop\MyChatBot\0.py", line 6, in <module> torchaudio._extension._init_ffmpeg() File "C:\Users\USER\AppData\Local\Programs\Python\Python311\Lib\site-packages\torchaudio\_extension\utils.py", line 87, in _init_ffmpeg raise ImportError("FFmpeg libraries are not found. Please install FFmpeg.") from err ImportError: FFmpeg libraries are not found. Please install FFmpeg.  my libtorchaudio_ffmpeg.pyd exists and it's path is correct, but ctypes can't seem to find it. how should i do? I have also downloaded ffmpeg. C:\Users\USER>ffmpeg ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers built with gcc 10.2.1 (GCC) 20200726  but still not working. how should i do?

Answer: You need to install ffmpeg libraries, not CLI. What the error message means is that the dependencies of libtorchaudio_ffmpeg.pyd is not found. The dependencies here mean the libraries that consist FFmpeg, such as libavcodec and libavformat. Usually installing ffmpeg CLI also intall the libraries, but I often see people use statically built ffmpeg CLI on Windows due to its ease of installation. I cannot tell what ffmpeg CLI you have, but if your ffmpeg CLI is statically built, it does not work. As of how to install dynamically built FFmpeg, I cannot advise. There seems to be no straightforward way to install dynamically built FFmpeg on Windows unless using Anacaonda.
Question: I have these three pictures from a SEM Microscope. One is the actual picture whilst the other two just indicated the presence of specific elements (Aluminium and Silicon) on the sample. I'd like to overlay them using Numpy and matplotlib so that I can then see where exactly the elements are, however not sure how to approach this on python, so far I've only gone as far as reading the picture files as np arrays: image_SEM = np.asarray(Image.open('Project_SEI.JPG')) image_Al = np.asarray(Image.open('Project_Al K.JPG')) image_Si = np.asarray(Image.open('Project_Si K.JPG'))  Thank you!   

Answer: I would be inclined to paste Si and Al images using a mask so that they only affect the SEM image where they are coloured and not where they are black/grey - else you will tend to reduce the contrast of your base image: from PIL import Image # Load images sei = Image.open('sei.jpg') si = Image.open('si.jpg') al = Image.open('al.jpg') # Make mask which only allows coloured areas to show siMask = si.convert('L') siMask.save('DEBUG-siMask.jpg') # Paste Si image over SEM image with transparency mask sei.paste(si, siMask) # Make mask which only allows coloured areas to show alMask = al.convert('L') alMask.save('DEBUG-alMask.jpg') # Paste Al image over SEM image with transparency mask sei.paste(al, alMask) sei.save('result.png')  DEBUG-siMask.jpg  DEBUG-alMask.jpg  result.jpg   Note that you could enhance the masks before use - for example you could median filter to remove small speckles, or you could contrast stretch to make the magenta/yellow shading come out more or less solid. For example, you can see the yellow is more solid than the magenta, which is because the yellow mask is brighter, so you could threshold the magenta mask to make it pure black and white which would make the magenta come out solid. So, I median-filtered out the speckles and changed the masking so that coloured areas are 50% transparent like this: #!/usr/bin/env python3 from PIL import Image, ImageFilter # Load images sei = Image.open('sei.jpg') si = Image.open('si.jpg') al = Image.open('al.jpg') # Make mask which only allows coloured areas to show siMask = si.convert('L') # Median filter mask to remove small speckles siMask = siMask.filter(ImageFilter.MedianFilter(5)) # Threshold mask and set opacity to 50% for coloured areas siMask = siMask.point(lambda p: 128 if p > 50 else 0) siMask.save('DEBUG-siMask.jpg') # Paste Si image over SEM image with transparency mask sei.paste(si, siMask) # Make mask which only allows coloured areas to show alMask = al.convert('L') # Median filter mask to remove small speckles alMask = alMask.filter(ImageFilter.MedianFilter(5)) # Threshold mask and set opacity to 50% for coloured areas alMask = alMask.point(lambda p: 128 if p > 50 else 0) alMask.save('DEBUG-alMask.jpg') # Paste Al image over SEM image with transparency mask sei.paste(al, alMask) sei.save('result.jpg')  That gives these masks and results:
Question: I'm encountering a weird warning with azure functions locally. Whenever I func start my function, I get these error messages: Found Python version 3.10.12 (python3). Azure Functions Core Tools Core Tools Version: 4.0.5455 Commit hash: N/A (64-bit) Function Runtime Version: 4.27.5.21554 [2023-11-14T10:02:39.795Z] Customer packages not in sys path. This should never happen! [2023-11-14T10:02:42.194Z] Worker process started and initialized.  In the host.json, extensionBundle version is [3.*, 4.0.0) In the local.settings.json, "FUNCTIONS_WORKER_RUNTIME": "python" The function app is based on the new model of python azure function (func init MyProjFolder --worker-runtime python --model V2 https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=linux%2Cisolated-process%2Cnode-v4%2Cpython-v2%2Chttp-trigger%2Ccontainer-apps&pivots=programming-language-python) My first interrogation is the first warning: Customer packages not in sys path. This should never happen!. I'm using a virtual environment. The function is starting correctly, but what is this warning? local.settings.json: { "IsEncrypted": false, "Values": { "FUNCTIONS_WORKER_RUNTIME": "python", "AzureWebJobsStorage": "UseDevelopmentStorage=true", "AzureWebJobsFeatureFlags": "EnableWorkerIndexing" } } 

Answer: This seems to be the issue with the latest version of Azure function Core tools (4.0.5455), which is published recently (6 days ago) as mentioned in the official doc.  I have created a python Azure function to check the same: Python Version: 3.11.5 Azure Functions Core Tools Core Tools Version: 4.0.5348 Commit hash: N/A (64-bit) Function Runtime Version: 4.24.5.21262   Didn't get any such warning:    Updated the Azure function Core tools version to 4.0.5455.  Running the same Azure Function again with below versions:   Python version 3.11.6 (py). Azure Functions Core Tools Core Tools Version: 4.0.5455 Commit hash: N/A (64-bit) Function Runtime Version: 4.27.5.21554
Question: data = {'SYMBOL': ['AAAA','AAAA','AAAA','AAAA','AAAA','AAAA','AAAA'] , 'EXPIRYDT': ['26-Oct-23','26-Oct-23','26-Oct-23','26-Oct-23','26-Oct-23','26-Oct-23','26-Oct-23'], 'STRIKE': [480, 500, 525, 425, 450, 480, 500], 'TYPE': ['CE', 'CE', 'CE', 'PE', 'PE', 'PE', 'PE'], 'CONTRACTS': [1, 31, 1, 0, 12, 2, 6], 'OPENINT': [4000, 25000, 1000, 1000, 64000, 2000, 5000], 'TIMESTAMP': ['4-Sep-23','4-Sep-23','4-Sep-23','4-Sep-23','4-Sep-23','4-Sep-23','4-Sep-23']} df=pd.DataFrame(data) result = df.groupby(['EXPIRYDT', 'TYPE']) df['CE_CONT'] = result['CONTRACTS'].transform('sum') df['PE_CONT'] = result['CONTRACTS'].transform('sum') df['CE_OI'] = result['OPENINT'].transform('sum') df['PE_OI'] = result['OPENINT'].transform('sum') print(df)  but i am not getting desired output i need output as SYMBOL EXPIRYDT STRIKE TYPE CONTRACTS OPENINT TIMESTAMP CE_CONT PE_CONT CE_OI PE_OI AAAA 26-Oct-23 480 CE 1 40000 4-Sep-23 33 20 30000 72000 AAAA 26-Oct-23 500 CE 31 25000 4-Sep-23 33 20 30000 72000 AAAA 26-Oct-23 525 CE 1 1000 4-Sep-23 33 20 30000 72000 AAAA 26-Oct-23 425 PE 0 1000 4-Sep-23 33 20 30000 72000 AAAA 26-Oct-23 450 PE 12 64000 4-Sep-23 33 20 30000 72000 AAAA 26-Oct-23 480 PE 2 2000 4-Sep-23 33 20 30000 72000 AAAA 26-Oct-23 500 PE 6 5000 4-Sep-23 33 20 30000 72000  after groupby i want  sum of OPENINT of TYPE CE TO CE_OI sum of OPENINT of TYPE PE TO PE_OI sum of CONTRACTS of TYPE CE to CE_CONT sum of CONTRACTS of TYPE PE to PE_CONT 

Answer: Code groupby & merge I chose to merge in too many ways because your original dataset may have multiple values in the EXPIRYDT column, and it is possible to assign different values depending on the EXPIRYDT. step1. aggregate by groupby tmp = df.groupby(['EXPIRYDT', 'TYPE']).agg(CONT=('CONTRACTS', 'sum'), OI=('OPENINT', 'sum'))\ .unstack().swaplevel(axis=1)  tmp: TYPE CE PE CE PE CONT CONT OI OI EXPIRYDT 26-Oct-23 33 20 30000 72000  Step2. make tmp to have single colmns and reset index tmp2 = tmp.set_axis(tmp.columns.map('_'.join), axis=1).reset_index()  tmp2:  EXPIRYDT CE_CONT PE_CONT CE_OI PE_OI 0 26-Oct-23 33 20 30000 72000  step3. merge df & tmp2 out = df.merge(tmp2, how='left')  out:
Question: I'm looking for an efficient method to compute the "order" of each item in a numpy array, with "order" defined as the number of preceding elements equal to the element. Example: order([4, 2, 3, 2, 6, 4, 4, 6, 2, 4]) [0 0 0 1 0 1 2 1 2 3]  Current solution loops in pure Python and is not fast enough: def order(A): cnt = defaultdict(int) O = np.zeros_like(A) for i, r in enumerate(A): O[i] = cnt[r] cnt[r] += 1 return O  I'm using order to implement scatter: def scatter(A, c): R = A % c I = c * order(R) + R B = np.full(np.max(I) + 1, -1) B[I] = A return B  This is useful for multi-threading. For example, if the scattered array contains addresses to write to then no two threads processing the array in parallel will see the same address. Question is are there numpy built-ins that I'm missing that I can use to make order faster and to remove the explicit looping?

Answer: Since what you're doing is essentially a Pandas cumcount, and Pandas uses NumPy internally, one idea would be to look at how they implemented cumcount, and do the same thing. If you read the Pandas code for cumcount, it is internally implemented in this way:  Sort the array, keeping track of where each element came from. Compare each element of the sorted array to the next element. If it is different, it is the start of a new run. (run) Work out the length of each group. (rep) Do a cumulative sum, incrementing by 1 for each element which is not part of a new run. (out) Track how much each group is affected by groups before it which should not count. (out[run]) Repeat the value to subtract by rep. Undo the initial sort to put elements back in their original place.  Here's how to do the same thing without relying on any of Pandas. def order(array): # https://github.com/pandas-dev/pandas/blob/v1.3.5/pandas/core/groupby/groupby.py#L1493 if len(array) == 0: return np.array([]) count = len(array) # Can remove 'stable' here to increase speed if you # don't care what order the order is assigned in ind = np.argsort(array, kind='stable') array = array[ind] run = np.r_[True, array[:-1] != array[1:]] rep = np.diff(np.r_[np.nonzero(run)[0], count]) out = (~run).cumsum() out -= np.repeat(out[run], rep) rev = np.empty(count, dtype=np.intp) rev[ind] = np.arange(count, dtype=np.intp) out = out[rev] return out  I find that this is approx 10x faster for arrays 1000 elements and larger.
Question: Update: numpy.random.choice is no longer parsed as an Object type. The example produces a String column as expected without any casting needed.  I got a pl.LazyFrame with a column of type Object that contains date representations, it also includes missing values (None). In a first step I would like to convert the column from Object to String however this results in a ComputeError. I can not seem to figure out why. I suppose this is due to the None values, sadly I can not drop those at the current point in time. import numpy as np import polars as pl rng = np.random.default_rng(12345) df = pl.LazyFrame( data={ "date": rng.choice( [None, "03.04.1998", "03.05.1834", "05.06.2025"], 100 ), } ) df.with_columns(pl.col("date").cast(pl.String)).collect() 

Answer: When Polars assigns the pl.Object type it essentially means: "I do not understand what this is." By the time you end up with this type, it is generally too late to do anything useful with it. In this particular case, numpy.random.choice is creating a numpy array of dtype=object >>> rng.choice([None, "foo"], 3) array([None, None, 'foo'], dtype=object)  Polars has native .sample() functionality which you could use to create your data instead. df = pl.select(date = pl.Series([None, "03.04.1998", "03.05.1834", "05.06.2025"]) .sample(100, with_replacement=True) ) # shape: (100, 1) # ┌────────────┐ # │ date │ # │ --- │ # │ str │ # ╞════════════╡ # │ null │ # │ 05.06.2025 │ # │ 03.05.1834 │ # │ 03.04.1998 │ # │ … │ # │ null │ # │ 03.04.1998 │ # │ 03.05.1834 │ # │ 03.04.1998 │ # └────────────┘
Question: I have a classification model, producing predictions for 4 classes in a tensor of shape (256, 1, 4)...256 is the batch size, while the "1" for the second dimension is due to some model internal logic and can be removed: preds.shape torch.Size([256, 1, 4])  The corresponding annotations are one-hot encoded, in a tensor of the same shape: targets.shape torch.Size([256, 1, 4])  so, in every row there is only one non-zero element: targets[0][0] = [1, 0, 0, 0]  I need to calculate the CrossEntropy loss of the model. I know that The CrossEntropyLoss expects class indices as the target, so I tried using argmax to determine the position of the 1 for each sample, and squeezed the extra dimension: vpredictions_squeezed = cls_scores.squeeze(1) targets = torch.argmax(targets.squeeze(1), dim=1) losses = torch.nn.CrossEntropyLoss(predictions_squeezed, targets)  But I'm getting the error: RuntimeError: Boolean value of Tensor with more than one value is ambiguous  What am I doing wrong here?

Answer: you can use direct call cross_entropy from torch.nn.functional import torch.nn.functional as F F.cross_entropy(predictions_squeezed, targets)  or you can rewrite your code, because this's class not a function: loss = nn.CrossEntropyLoss() output = loss(input, target)
Question: Lets say I have a dataframe such as: CATEGORY Value a v1 a v2 a v3 a v4 a v5 b v6 b v7 b v8  Now, if i want to plot this distributions by category, i could use something like: sns.histplot(data,"Value",hue="CATEGORY",stat="percent").  The problem with this is that category "a" represents 5/8 of the sample and "b" is 3/8. The histograms will reflect this. I want to plot in a way that each histogram will have an area of 1, instead of 5/8 and 3/8. Below is an example of how it looks like now  But each of those areas should be one. I thought of maybe iterating by category and plotting one by one

Answer: As per this answer of the duplicate, use common_norm=False. Also see seaborn histplot and displot output doesn't match. This is not specific to stat='percent'. Other options are 'frequency', 'probability', and 'density'. import seaborn as sns import matplotlib.pyplot as plt tips = sns.load_dataset('tips') fig, axes = plt.subplots(nrows=2, figsize=(20, 10), tight_layout=True) sns.histplot(data=tips, x='total_bill', hue='day', stat='percent', multiple='dodge', bins=30, common_norm=True, ax=axes[0]) sns.histplot(data=tips, x='total_bill', hue='day', stat='percent', multiple='dodge', bins=30, common_norm=False, ax=axes[1]) axes[0].set_title('common_norm=True', fontweight='bold') axes[1].set_title('common_norm=False', fontweight='bold') handles = axes[1].get_legend().legend_handles for ax in axes: for c in ax.containers: ax.bar_label(c, fmt=lambda x: f'{x:0.2f}%' if x > 0 else '', rotation=90, padding=3, fontsize=8, fontweight='bold') ax.margins(y=0.15) ax.spines[['top', 'right']].set_visible(False) ax.get_legend().remove() _ = fig.legend(title='Day', handles=handles, labels=tips.day.cat.categories.tolist(), bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)   sns.displot g = sns.displot(data=tips, kind='hist', x='total_bill', hue='day', stat='percent', multiple='dodge', bins=30, common_norm=False, height=5, aspect=4) ax = g.axes.flat[0] # ax = g.axes[0][0] also works for c in ax.containers: ax.bar_label(c, fmt=lambda x: f'{x:0.2f}%' if x > 0 else '', rotation=90, padding=3, fontsize=8, fontweight='bold')
Question: I have a following data frame which I converted to pandas pivot table having two indexes "Date" and "Rating. The values are sorted in columns A, B and C.  I would like to find a solution which will subtract the values for each column and rating for consecutive days. Say, the change in A from 03/01/2007 to 02/01/2007 for rating M would be 0.4179 - 0.4256 = -0.0077. The subtraction won't always be performed on a one day difference. But it will always be the (new date - the old date). The results I'm looking for can be found in the table below: 

Answer: If your dataframe is correctly sorted (or use df.sort_values('Date')), you can use groupby_diff: # Replace ['A'] with ['A', 'B', 'C'] df['A_diff'] = df.groupby('Rating')['A'].diff().fillna(0)  Output: >>> df Date Rating A A_diff 0 02/01/2007 M 0.4256 0.0000 1 02/01/2007 MM 0.4358 0.0000 2 02/01/2007 MMM 0.4471 0.0000 3 03/01/2007 M 0.4179 -0.0077 4 03/01/2007 MM 0.4325 -0.0033 5 03/01/2007 MMM 0.4476 0.0005 6 04/01/2007 M 0.4173 -0.0006 7 04/01/2007 MM 0.4316 -0.0009 8 04/01/2007 MMM 0.4469 -0.0007  If you don't know how many columns you have, you can try: cols = df.columns[2:] df[cols] = df.groupby('Rating')[cols].diff().fillna(0)
Question: I want to create a unique ID incrementation for my Python subclasses using the abstract method, but I don't know how to separate each subclass's set of ID values. Here is my code: from dataclasses import dataclass, field from itertools import count @dataclass class Basic: identifier: int = field(default_factory=count().__next__, init=False) def __init_subclass__(cls, **__): super().__init_subclass__(**__) # cls.identifier: int = field(default_factory=count().__next__, init=False) class A(Basic): pass class B(Basic): pass  The id values are shared between subclasses when I want to separate them: >>> import stack >>> stack.A() A(identifier=0) >>> stack.B() B(identifier=1)  Do you know how to solve the problem? I think the __init_subclass__ is a solution, but I'm unsure how to make it work.

Answer: The dataclasses library does not fit for your use case. Think a data class as a mutable namedtuple with defaults. I recommend implementing concrete classes. However, if you insist, you can do like the following by defining another decorator which augments an input class before calling the dataclasses.dataclass(). (This assumes using Python 3.10 or later.) from dataclasses import dataclass, field from itertools import count def dataclass_with_id(cls): setattr(cls, 'identifier', field(default_factory=count().__next__, init=False)) cls.__annotations__['identifier'] = int return dataclass(cls) @dataclass_with_id class A: pass @dataclass_with_id class B: pass print(A(), A()) print(B(), B())  If you want to do this work in the __init_subclass__() of a common base class, you need to hack the internal implementation of the dataclasses module. But don't do it because it will be broken for future Python versions.
Question: import pandas as pd mydata = {"Key" : [567, 568, 569, 570, 571, 572] , "Sprint" : ["Max1;Max2", "Max2", "DI001 2", "DI001 25", "DAS 100" , "DI001 101"]} df = pd.DataFrame(mydata) df ["sprintlist"]= df["Sprint"].str.split(";") print (df)  From this dataframe, I want to extract only the numbers that appears in the last part of the string from column "Sprintlist" for each value in the list to the new list "Sprintnumb" as show below Expected output:  In one of my previous query, I got clarity on how to extract the number when only one value present in "Sprint" column. I tried using lambda function to achieved the desired output but getting errors "str' object has no attribute 'str'"  df["Sprint Number"] = df.Sprint.str.extract(r"(\d+)$").astype(int) 

Answer: Use Series.explode with Series.str.extractall, converting to numeric and aggregate lists: df["Sprint Number"] = (df["sprintlist"].explode() .str.extractall(r"(\d+)$")[0] .astype(int) .groupby(level=0) .agg(list)) print (df) Key Sprint sprintlist Sprint Number 0 567 Max1;Max2 [Max1, Max2] [1, 2] 1 568 Max2 [Max2] [2] 2 569 DI001 2 [DI001 2] [2] 3 570 DI001 25 [DI001 25] [25] 4 571 DAS 100 [DAS 100] [100] 5 572 DI001 101 [DI001 101] [101]  Or use list comprhension with regex: df["Sprint Number"] = [[int(re.search('(\d+)$', y).group(0)) for y in x] for x in df["sprintlist"]] print (df) Key Sprint sprintlist Sprint Number 0 567 Max1;Max2 [Max1, Max2] [1, 2] 1 568 Max2 [Max2] [2] 2 569 DI001 2 [DI001 2] [2] 3 570 DI001 25 [DI001 25] [25] 4 571 DAS 100 [DAS 100] [100] 5 572 DI001 101 [DI001 101] [101]  If possible some string not ends with number add assign operator := with testing None: import re mydata = {"Key" : [567, 568, 569, 570, 571, 572] , "Sprint" : ["Max1;Max", "Max2", "DI001 2", "DI001 25", "DAS 100" , "DI001 101"]} df = pd.DataFrame(mydata) df ["sprintlist"]= df["Sprint"].str.split(";") df["Sprint Number"] = [[int(m.group(0)) for y in x if( m:=re.search('(\d+)$', y)) is not None] for x in df["sprintlist"]] print (df) Key Sprint sprintlist Sprint Number 0 567 Max1;Max [Max1, Max] [1] 1 568 Max2 [Max2] [2] 2 569 DI001 2 [DI001 2] [2] 3 570 DI001 25 [DI001 25] [25] 4 571 DAS 100 [DAS 100] [100] 5 572 DI001 101 [DI001 101] [101]
Question: When looping a generator in StreamingResponse() using FastAPI/starlette https://www.starlette.io/responses/#streamingresponse how can we tell if the connection was somehow disconnected, so a event could be fired and handled somewhere else? Scenario: writing an API with text/event-stream, need to know when client closed the connection.

Answer: Consider using request.is_disconnected(). From Starlette's docs:  In some cases such as long-polling, or streaming responses you might need to determine if the client has dropped the connection. You can determine this state with disconnected = await request.is_disconnected().  Unfortunately, there seems to be no other documentation regarding this API. Have a look at the MR that introduced this feature: https://github.com/encode/starlette/pull/320
Question: I have the following pandas dataframe import pandas as pd foo = pd.DataFrame({'country': {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}, 'unweighted': {0: 18.0, 1: 16.9, 2: 13.3, 3: 11.3, 4: 13.1}, 'weighted_1': {0: 17.7, 1: 15.8, 2: 14.0, 3: 11.2, 4: 12.8}, 'weighted_2': {0: 17.8, 1: 15.8, 2: 14.0, 3: 11.2, 4: 12.8}}) country unweighted weighted_1 weighted_2 0 a 18.0 17.7 17.8 1 b 16.9 15.8 15.8 2 c 13.3 14.0 14.0 3 d 11.3 11.2 11.2 4 e 13.1 12.8 12.8  And I am using the following code to produce the barchart using plotly_express import plotly.express as px px.bar( so, x='country', y=['unweighted', 'weighted_1', 'weighted_2'], barmode='group', )   I would like to display also the text at each bar. I tried px.bar( so, x='country', y=['unweighted', 'weighted_1', 'weighted_2'], text=['unweighted', 'weighted_1', 'weighted_2'], barmode='group', )  but it doesnt work. How could I do that ?

Answer: There are automatic annotations in the annotations. import plotly.express as px px.bar( foo, x='country', y=['unweighted', 'weighted_1', 'weighted_2'], text_auto=True, barmode='group', )