eshangj/stackoverflow_q_and_a_sample huggingface dataset:
Question: I've got this pandas code: df['date_col'] = pd.to_datetime(df['date_col'], format='%Y-%m-%d') row['date_col'] = pd.to_datetime(row['date_col'], format='%Y-%m-%d') df = df[(df['groupby_col'] == row['groupby_col']) & (row['date_col'] - df['date_col'] <= timedelta(days = 10)) & (row['date_col'] - df['date_col'] > timedelta(days = 0))] row['mean_col]' = df['price_col'].mean()  The name row comes from the fact that this function was applied by a lambda construct. I'm subsetting df with 2 types of conditions:    A condition on values equality on a column named "groupby_col",     Multiple onditions on time ranges based on the "date_col" column that features timestamps.    I'm pretty sure that filter is the correct module to use: df.filter(condition_1 & condition_2)  but i'm struggling to write the conditions. In order to embed condition 1 do i have to nest a filter condition or a when is the correct choice? How do i translate the timedelta condition? How do i replicate the lambda approach?

Answer: It's a bit hard to understand your example without test data. But if I try to create some sample data import polars as pl import datetime df = pl.DataFrame({ "date_col": ['2023-01-01','2023-01-02', '2023-01-03'], "groupby_col": [1,2,3], }) row = pl.DataFrame({ "date_col": ['2023-01-07','2023-01-08', '2023-01-25'], "groupby_col": [1,2,3], }) df = df.with_columns(pl.col('date_col').str.to_datetime().cast(pl.Date)) row = row.with_columns(pl.col('date_col').str.to_datetime().cast(pl.Date))  then you can filter on multiple conditions by joining two dataframes first and then filtering: (df .join(row, on=["groupby_col"]) .filter( pl.col("date_col_right") - pl.col("date_col") >= datetime.timedelta(days=0), pl.col("date_col_right") - pl.col("date_col") < datetime.timedelta(days=10), ).drop('date_col_right') ) shape: (2, 2) ┌────────────┬─────────────┐ │ date_col ┆ groupby_col │ │ --- ┆ --- │ │ date ┆ i64 │ ╞════════════╪═════════════╡ │ 2023-01-01 ┆ 1 │ │ 2023-01-02 ┆ 2 │ └────────────┴─────────────┘
Question: My code finds an unknown (0<alpha<1), its precision depends on another parameter (dm). Finally, alpha is determined with e.g. 20 digits but depending on dm, alpha should be kept until definite (which is known during execution=njj) digit. At the end, I need to substitute njj in format command as following: njj= 8 ;alpha= 0.0004258819580078126 # I need this alpha= 0.00042588 print('{:.njj f}'.format(alpha)) But it doesn't work! It shows: ValueError: Format specifier missing precision

Answer: this is quite a good question. i find that this works nicely: njj= 8 alpha= 0.0004258819580078126 # I need this alpha= 0.00042588 print(f'{alpha:.{njj}f}')  which gives this: 0.00042588  but also, you could do this: print(round(alpha, njj))  update: As per the comments below from @Mark, the round() function produces a different number of decimal places compared to the formatted f-string method when there are trailing Zero's. So the user would need to decide which one they wanted to see.
Question: I am using rng = np.random.default_rng(seed=None) for testing purposes following documentation. My program is a scientific code, so it is good to have some random values to test it, but if I found a problem with the code's result, I would like to get the seed back and try again to find the problem. Is there any way to do that? Things like this question does not seem to work with a Generator:  AttributeError: 'numpy.random._generator.Generator' object has no attribute 'get_state'  Of course I can always try a set of predefined seeds, but that is not what I want.

Answer: Use __getstate__, __setstate__ and forget about seed... it's just a parameter for default_rng! # old instance rng = np.random.default_rng(seed=None) s_old = rng.__getstate__() # new instance rng = np.random.default_rng(seed=123123) # seed=anything, also None s_new = rng.__getstate__() print(s_old == s_new) #False # update "seed" rng.__setstate__(s_old) # pass the old "seed" s_recovered = rng.__getstate__() print(s_old == s_recovered) #True  Then when you call methods to generate random numbers you will be able to replicate the randomness.  Alternative of the dunder methods # get the state s_old = rng.bit_generator.state  and # set the state of the new instance of rng rng.bit_generator.state = s_old
Question: Looking for a way to use Python 3.10 on a compute resource associated to Azure ML Studio It appears 3.10 is available with ML Studio and we select 3.10 with SDK2 from the kernel selection dropdown but when running a "python --version" on the terminal, it says v 3.8.5. Is there a way to get Azure ML Studio to use a different version of Python? We've tried the environment option but had no luck. Looks like the kernel selection option does not match what the OS is running, perhaps it's designed to work this way?

Answer: That is because of the selected conda environment. There will be multiple environments created when you create a compute instance. To see, run the conda command below: %%sh conda info --env  This lists the environments present. However, if you run this in a notebook, you cannot see which environment you are in. So, execute these commands in the terminal. Open the compute and select Terminal.  There, you will see the default is Python 3.8.  You can also see this with the commands below: conda info --env or conda env list or echo $CONDA_DEFAULT_ENV  Output:  Whenever you select the kernel, it doesn't switch the environment in the terminal; that only changes in the notebook Python code. Whatever command you run in a subprocess or using %%sh, it takes the default Python environment. import sys, platform print(sys.version) print(platform.python_version())
Question: I am currently converting code from pandas to polars as I really like the api. This question is a more generally question to a previous question of mine (see here) I have the following dataframe # Dummy data df = pl.DataFrame({ "Buy_Signal": [1, 0, 1, 0, 1, 0, 0], "Returns": [0.01, 0.02, 0.03, 0.02, 0.01, 0.00, -0.01], })  I want to ultimately do aggregations on column Returns conditional on different intervals - which are given by column Buy_Signal. In the above case the length is from each 1 to the end of the dataframe. The resulting dataframe should therefore look like this shape: (15, 2) ┌───────┬─────────┐ │ group ┆ Returns │ │ --- ┆ --- │ │ i64 ┆ f64 │ ╞═══════╪═════════╡ │ 1 ┆ 0.01 │ │ 1 ┆ 0.02 │ │ 1 ┆ 0.03 │ │ 1 ┆ 0.02 │ │ 1 ┆ 0.01 │ │ 1 ┆ 0.0 │ │ 1 ┆ -0.01 │ │ 2 ┆ 0.03 │ │ 2 ┆ 0.02 │ │ 2 ┆ 0.01 │ │ 2 ┆ 0.0 │ │ 2 ┆ -0.01 │ │ 3 ┆ 0.01 │ │ 3 ┆ 0.0 │ │ 3 ┆ -0.01 │ └───────┴─────────┘  One approach posted as an answer to my previous question is the following: # Build overlapping group index idx = df.select(index= pl.when(pl.col("Buy_Signal") == 1) .then(pl.int_ranges(pl.int_range(pl.len()), pl.len() )) ).explode(pl.col("index")).drop_nulls().cast(pl.UInt32) # Join index with original data df = (df.with_row_index() .join(idx, on="index") .with_columns(group = (pl.col("index") == pl.col("index").max()) .shift().cum_sum().backward_fill() + 1) .select(["group", "Returns"]) )  Question: Are there other solutions to this problem that are both readable and fast? My actual problem contains much larger datasets. Thanks

Answer: For completeness, here is an alternative solution that doesnt rely on experimental functionality. ( df .with_columns( pl.col("Buy_Signal").cum_sum().alias("group") ) .with_columns( pl.int_ranges(pl.col("group").min(), pl.col("group")+1) ) .explode("group") .sort("group") )  Output. shape: (15, 3) ┌────────────┬─────────┬───────┐ │ Buy_Signal ┆ Returns ┆ group │ │ --- ┆ --- ┆ --- │ │ i64 ┆ f64 ┆ i64 │ ╞════════════╪═════════╪═══════╡ │ 1 ┆ 0.01 ┆ 1 │ │ 0 ┆ 0.02 ┆ 1 │ │ 1 ┆ 0.03 ┆ 1 │ │ 0 ┆ 0.02 ┆ 1 │ │ 1 ┆ 0.01 ┆ 1 │ │ … ┆ … ┆ … │ │ 0 ┆ 0.0 ┆ 2 │ │ 0 ┆ -0.01 ┆ 2 │ │ 1 ┆ 0.01 ┆ 3 │ │ 0 ┆ 0.0 ┆ 3 │ │ 0 ┆ -0.01 ┆ 3 │ └────────────┴─────────┴───────┘
Question: I'm trying to figure out the multiple inheritance in Python, but all articles I find are limited to simple cases. Let's consider the following example: class Vehicle: def __init__(self, name: str) -> None: self.name = name print(f'Creating a Vehicle: {name}') def __del__(self): print(f'Deleting a Vehicle: {self.name}') class Car(Vehicle): def __init__(self, name: str, n_wheels: int) -> None: super().__init__(name) self.wheels = n_wheels print(f'Creating a Car: {name}') def __del__(self): print(f'Deleting a Car: {self.name}') class Boat(Vehicle): def __init__(self, name: str, n_props: int) -> None: super().__init__(name) self.propellers = n_props print(f'Creating a Boat: {name}') def __del__(self): print(f'Deleting a Boat: {self.name}') class Amfibii(Car, Boat): def __init__(self, name: str, n_wheels: int, n_props: int) -> None: Car.__init__(self, name, n_wheels) Boat.__init__(self, name, n_props) print(f'Creating an Amfibii: {name}') def __del__(self): print(f'Deleting an Amfibii: {self.name}') my_vehicle = Amfibii('Mazda', 4, 2)  I want to understand the order of calling constructors and destructors, as well as the correct and general use of the 'super' keyword. In the example above, I get the following error:  super().__init__(name) TypeError: Boat.__init__() missing 1 required positional argument: 'n_props'  How should I correctly call constructors of both parents, which have different sets of constructor arguments?

Answer: Thanks to the comments and the following article, I understood it. https://rhettinger.wordpress.com/2011/05/26/super-considered-super/  Regarding the constructors' arguments, they should be named. In this way, every level strips what it needs and passes it to the next one using super()  Every class calls super().__init__() only once. The following classes in the MRO order are responsible for continuing the initialization.   The updated example: class Vehicle: def __init__(self, name: str) -> None: self.name = name print(f'Creating a Vehicle: {name}') def go(self): print('Somehow moving...') assert not hasattr(super(), 'go') class Car(Vehicle): def __init__(self, n_wheels: int, **kwargs) -> None: super().__init__(**kwargs) self.wheels = n_wheels print(f'Creating a Car: {self.name}') def go(self): print('Riding...') super().go() class Boat(Vehicle): def __init__(self, n_props, **kwargs) -> None: super().__init__(**kwargs) self.propellers = n_props print(f'Creating a Boat: {self.name}') def go(self): print('Swimming...') super().go() class Amfibii(Car, Boat): def __init__(self, **kwargs) -> None: super().__init__(**kwargs) print(f'Creating an Amfibii: {self.name}') def go(self): print('Riding or swimming...') super().go() my_vehicle = Amfibii(name='Mazda', n_wheels=4, n_props=2) my_vehicle.go()  It's a bit cumbersome (gently speaking), isn't it? EDIT: I updated the code according co the comments.
Question: Trying ruff for the first time and I'm not being able to sort imports alphabetically, using default settings. According to docs ruff should be very similar to isort. Here is a short example with unsorted imports import os import collections  Run ruff command $ ruff format file.py 1 file left unchanged  But if I run isort the imports are properly sorted $ isort file.py Fixing .../file.py  What am I doing wrong?

Answer: According to https://github.com/astral-sh/ruff/issues/8926#issuecomment-1834048218:  In Ruff, import sorting and re-categorization is part of the linter, not the formatter. The formatter will re-format imports, but it won't rearrange or regroup them, because the formatter maintains the invariant that it doesn't modify the program's AST (i.e., its semantics and behavior). To get isort-like behavior, you'd want to run ruff check --fix with --select I or adding extend-select = ["I"] to your pyproject.toml or ruff.toml.
Question: ┌───────┬─────┐ │ group ┆ var │ │ --- ┆ --- │ │ i64 ┆ str │ ╞═══════╪═════╡ │ 1 ┆ x │ │ 1 ┆ x │ │ 2 ┆ x │ │ 2 ┆ y │ │ 3 ┆ y │ │ 3 ┆ y │ └───────┴─────┘  Suppose the above dataframe is called df and I want to get the percentage of variables named 'x' by group. The following gives me ValueError: could not convert value 'Unknown' as a Literal. Can someone explain why? df.group_by('group').agg( pl.mean((pl.col('var') == 'x').cast(pl.Int8)) ) 

Answer: As mentioned in the documentation, pl.mean() is just a syntactic sugar for pl.col(columns).mean(). Your code doesn't work because pl.mean() expects *columns: str (column names) as input, not Expr. But you can use pl.col(columns).mean() instead: df = df.group_by('group', maintain_order=True).agg( (pl.col('var') == 'x').mean() )  so you get shape: (3, 2) ┌───────┬─────┐ │ group ┆ var │ │ --- ┆ --- │ │ i64 ┆ f64 │ ╞═══════╪═════╡ │ 1 ┆ 1.0 │ │ 2 ┆ 0.5 │ │ 3 ┆ 0.0 │ └───────┴─────┘
Question: I want to end up with a list with 48 620 nested lists, containing 9 zeros and 9 ones in different orders. from itertools import permutations print(list(permutations('000000000111111111', r=18)))  I assume the code above works, but every 0 and 1 is treated like an individual symbol, so for every ordering I get tons of repeats: ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ('0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1') ...  So, basically, how do I shuffle a list in every possible way, excluding repeats? I tried to use every method from itertools, but I didn't find one that specifically does what i need.

Answer: Where 18 is the length of the list you want to generate and 9 is how many of them should be 0: for x in itertools.combinations(range(18),9): print(tuple(('0' if i in x else '1' for i in range(18))))  The idea here is to use combinations to choose the set of locations that will be 0 for each of (in your example's case) 48620 lists.
Question: I have some polars DataFrames over which I want to compute some row-wise statistics. For some there is a .list.func function which exists (eg list.mean), however, for those which don't have a dedicated function I believe I must use list.eval. For the following example data: df = pl.DataFrame({ 'a': [1,10,1,.1,.1, np.NAN], 'b': [2, 8,1,.2, np.NAN,np.NAN], 'c': [3, 6,2,.3,.2, np.NAN], 'd': [4, 4,3,.4, np.NAN,np.NAN], 'e': [5, 2,3,.5,.3, np.NAN], }, strict=False)  I have managed to come up with the following expression. It seems that list.eval returns a list (which I suppose is more generic) so I need to call .explode on the resulting 1-element list to get back a single value. The resulting column takes the name of the first column, so I then need to call .alias to give it a more meaningful name. df.select( pl.concat_list( pl.all().fill_nan(None) ) .list.eval(pl.element().quantile(0.25)) .explode() .alias('q1') )  Is this the recommended way of computing row-wise?

Answer: I would unpivot and join here. It should be faster than .list.eval plus it let's you more easily add other row wise aggregations. Note I've added q2,q3,q4 to the agg ( (_df:=df.with_row_index('i')) .join( _df .unpivot(index='i') .group_by('i') .agg( pl.col('value').quantile(x).alias(q) for q,x in {'q1':0.25,'q2':0.50, 'q3':0.75, 'q4':1}.items() ), on='i' ) .sort('i') .drop('i') ) shape: (6, 9) ┌──────┬─────┬─────┬─────┬───┬─────┬─────┬─────┬──────┐ │ a ┆ b ┆ c ┆ d ┆ … ┆ q1 ┆ q2 ┆ q3 ┆ q4 │ │ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │ │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ ┆ f64 ┆ f64 ┆ f64 ┆ f64 │ ╞══════╪═════╪═════╪═════╪═══╪═════╪═════╪═════╪══════╡ │ 1.0 ┆ 2.0 ┆ 3.0 ┆ 4.0 ┆ … ┆ 2.0 ┆ 3.0 ┆ 4.0 ┆ 5.0 │ │ 10.0 ┆ 8.0 ┆ 6.0 ┆ 4.0 ┆ … ┆ 4.0 ┆ 6.0 ┆ 8.0 ┆ 10.0 │ │ 1.0 ┆ 1.0 ┆ 2.0 ┆ 3.0 ┆ … ┆ 1.0 ┆ 2.0 ┆ 3.0 ┆ 3.0 │ │ 0.1 ┆ 0.2 ┆ 0.3 ┆ 0.4 ┆ … ┆ 0.2 ┆ 0.3 ┆ 0.4 ┆ 0.5 │ │ 0.1 ┆ NaN ┆ 0.2 ┆ NaN ┆ … ┆ 0.2 ┆ 0.3 ┆ NaN ┆ NaN │ │ NaN ┆ NaN ┆ NaN ┆ NaN ┆ … ┆ NaN ┆ NaN ┆ NaN ┆ NaN │ └──────┴─────┴─────┴─────┴───┴─────┴─────┴─────┴──────┘  I used the walrus operator to create _df so as to not have to invoke .with_row_index twice. If you prefer you can just do df=df.with_row_index('i') first instead.
Question: I work on a large project and I'd slowly like to enfore pydocstyle using ruff. However, many files will fail on e.g. D103 "undocumented public function". I'd like to start with enforcing it on a few specific files, so I'd like to write something like select = ["D"] [tool.ruff.ignore-except-per-file] # this config does not exist # ignore D103 but on all files, except the ones that pass "properly_formatted_module1.py" = ["D103"] "properly_formatted_module2.py" = ["D103"]  I don't think this is possible; the only way I see is to explicitly write down ALL of the file names in a [tool.ruff.extend-per-file-ignores]. There are a few hunderd of them so that's not really nice to do.

Answer: You can invert the file selection in the (extend-)per-file-ignores section to ignore for example D103 on all files except the ones that do match the pattern. from the Ruff documentation for the per-file-ignores:  A list of mappings from file pattern to rule codes or prefixes to exclude, when considering any matching files. An initial '!' negates the file pattern.  And the corresponding example in a pyproject.toml: # Ignore `D` rules everywhere except for the `src/` directory. "!src/**.py" = ["D"]
Question: I am using openai to convert text into audio , how ever this error always pops up : AttributeError: 'HttpxBinaryResponseContent' object has no attribute 'with_streaming_response' I have tried the stream_to_field() function but it neither works def audio(prompt): speech_file_path=Path('C:\\Users\\beni7\\Downloads\\proyectos_programacion\\proyecto_shorts\\audio').parent / "speech.mp3" response = openai.audio.speech.create( model="tts-1", voice="alloy", input=prompt ) response.with_streaming_response.method(speech_file_path) 

Answer: .with_streaming_response is a method on speech. You can try the following: def audio(prompt): speech_file_path="<file path>" with client.audio.speech.with_streaming_response.create( model="tts-1", voice="alloy", input=prompt, ) as response: response.stream_to_file(speech_file_path)
Question: I am trying to upload an attachment via an API. I can make it work in the software's Swagger environment with this: curl -X 'POST' \ 'https://demo.citywidesolutions.com/v4_server/external/v1/maintenance/service_requests/9/attached_files' \ -H 'accept: */*' \ -H 'Content-Type: multipart/form-data' \ -H 'Authorization: Bearer 123456789' \ -F 'description=' \ -F 'data=@This is my file.pdf;type=application/pdf'  When I try to do the same with python requests I get a 400 error with a message of missing metadata. Here is what I am trying to pass with Python: import requests Headers = {'accept': '*/*', 'Content-Type': 'multipart/form-data', 'Authorization': 'Bearer 123456789'} Attachment = {'description': '', 'data': open('C:/This is my file.pdf', 'rb')} Response = requests.post(url='https://demo.citywidesolutions.com/v4_server/external/v1/maintenance/service_requests/9/attached_files', headers=Headers, files=Attachment)  From that I get a 400 response and the JSON says Missing Metadata. What am I missing here?

Answer: You could try explicitly setting the file type in your code; you do so in the curl method, but not in the Python script. Also, the requests library is able to handle 'Content-Type', so typically you don't need to set it. And the description parameter may be expected as a tuple. Here are all those changes; I have not tested since I do not have access to the endpoint: import requests headers = { 'accept': '*/*', 'Authorization': 'Bearer 123456789' } # excluded content-type files = { 'description': (None, ''), 'data': ('blank.pdf', open('blank.pdf', 'rb'), 'application/pdf') #added application/pdf format } url = 'https://demo.citywidesolutions.com/v4_server/external/v1/maintenance/service_requests/9/attached_files' response = requests.post(url, headers=headers, files=files)
Question: I paginated the search result. For the first, query set gives me perfect result , but the pagination set all pages, and I get all data from database by clicking on any page number. Here is my code: This is the controller which I added :  class MyCustomWeb(http.Controller): @http.route(['/customer', '/customer/page/<int:page>'], type="http", auth="user", website=True) def customer_kanban(self, page=1, search=None, **post): domain = [] if search: domain.append(('name', 'ilike', search)) post["search"] = search customer_obj = request.env['res.partner'].sudo().search(domain) total = customer_obj.sudo().search_count([]) pager = request.website.pager( url='/customer', total=total, page=page, step=3, ) offset = pager['offset'] customer_obj = customer_obj[offset: offset + 5] return request.render('my_module.customer_form', { 'search': search, 'customer_details': customer_obj, 'pager': pager, })  This is the XML code : the template of customer website :  <template id="customer_form" name="Customers"> <t t-call="website.layout"> <div> <div class="col-md-6"> <br/> <div> <form action="/customer" method="post"> <t t-call="website.website_search_box"> </t> <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> <div> <section> <div class="customer_details"> <center> <h3>Customers</h3> </center> </div> <br/> <div class="oe_product_cart_new row" style="overflow: hidden;"> <t t-foreach="customer_details" t-as="customers"> <div class="col-md-3 col-sm-3 col-xs-12" style="padding:1px 1px 1px 1px;"> <div style="border: 1px solid #f0eaea;width: 150px;height: auto;padding: 7% 0% 10% 0%; border-radius: 3px;overflow: hidden; margin-bottom: 44px !important;width: 100%;height: 100%;"> <div class="oe_product_image"> <center> <div style="width:100%;overflow: hidden;"> <img t-if="customers.image_1920" t-attf-src="/web/image/res.partner/#{customers.id}/image_1920" class="img oe_product_image" style="padding: 0px; margin: 0px; width:auto; height:100%;"/> </div> <div style="text-align: left;margin: 10px 15px 3px 15px;"> <t t-if="customers.name"> <span t-esc="customers.name" style="font-weight: bolder;color: #3e3b3b;"/> <br/> </t> </div> </center> </div> </div> </div> </t> </div> <div class="products_pager form-inline justify-content-center mt-3"> <t t-call="website.pager"> <t t-set="_classes">mt-2 ml-md-2</t> </t> </div> </section> <br/> <hr class="border-600 s_hr_1px w-100 mx-auto s_hr_dotted"/> </div> </form> </div> </div> </div> </t> </template>  Any help please? Thanks.

Answer: Since you have not supplied a domain, customer_obj.sudo().search_count([]) will return the whole amount of records in the model. Alternatively, you can use len(customer_obj) or provide a domain inside the search_count as well. total = len(customer_obj) pager = request.website.pager( url='/customer', total=total, page=page, url_args={'search': search}, step=3, )
Question: When I call fig.set_tight_layout(True) on a Matplotlib figure, I receive this deprecation warning: The set_tight_layout function will be deprecated in a future version. Use set_layout_engine instead.  How do I call set_layout_engine so as to match the current behavior as closely as possible? Environment: OS: Mac Python: 3.10.6 matplotlib: 3.7.2 

Answer: From: https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.Figure.set_layout_engine fig.set_layout_engine("tight")