eshangj/stackoverflow_q_and_a_sample huggingface dataset:
Question: Suppose you have a dataframe like this data = {'site': ['A', 'A', 'B', 'B', 'C', 'C'], 'item': ['x', 'x', 'x', 'x', 'x', 'x'], 'date': ['2023-03-01', '2023-03-10', '2023-03-20', '2023-03-27', '2023-03-5', '2023-03-12'], 'quantity': [10,20,30, 20, 30, 50]} df_sample = pd.DataFrame(data=data) df_sample.head()  Where you have different sites and items with a date and quantity. Now, what you want to do is calculate the correlation between say site A and site B for item x and their associated quantity. Although, they could be of different length in the dataframe. How would you go about doing this. The actual data in consideration here can be found here here. Now, what I tried was just setting up two different dataframes like this df1 = df_sample[(df_sample['site'] == 'A']) & (df_sample['item'] == 'x')] df2 = df_sample[(df_sample['site'] == 'B']) & (df_sample['item'] == 'x')]  then just force them to have the same size, and calculate the correlation coefficient from there but I am sure there is a better way to do this.

Answer: Reshape to wide form with pivot_table and add zeros to missing data points, this will allow a correct comparison. You can then select the item you want and compute the correlation of all combinations of columns with corr: tmp = df_sample.pivot_table(index='date', columns=['item', 'site'], values='quantity', fill_value=0) out = tmp['x'].corr()  Output: site A B C site A 1.000000 -0.449618 -0.442627 B -0.449618 1.000000 -0.464363 C -0.442627 -0.464363 1.000000  Intermediate tmp: item x site A B C date 2023-03-01 10.0 0.0 0.0 2023-03-10 20.0 0.0 0.0 2023-03-12 0.0 0.0 50.0 2023-03-20 0.0 30.0 0.0 2023-03-27 0.0 20.0 0.0 2023-03-5 0.0 0.0 30.0
Question: The behavior of the str.find() method in polars differs from str.find() in pandas in Python. Is there a parameter for processing utf-8 characters? Or is it a bug? Example code in python: import polars as pl # Define a custom function that wraps the str.find() method def find_substring(s, substring): return int(s.find(substring)) # Test df df = pl.DataFrame({ "text": ["testтестword",None,''] }) # Apply the custom function to the "text" column using map_elements() substr = 'word' df = df.with_columns( pl.col('text').str.find(substr,literal=True,strict=True).alias('in_polars'), pl.col("text").map_elements(lambda s: find_substring(s, substr), return_dtype=pl.Int64).alias('find_check') ) print(df)  Results:  There is no parameter in the documentation for setting the character encoding. Using my function is a solution, but it's very slow. Can you suggest something faster and without map_elements? Thanks. pl.col("text").map_elements(lambda s: find_substring(s, substr), return_dtype=pl.Int64).alias('find_check') 

Answer: There is an open issue on the Github tracker.  https://github.com/pola-rs/polars/issues/14190   I think we should update the docs to make clear that we return byte offsets.   As for the actual goal - it seems you want split a string into 2 parts and take the right hand side. You could use regex e.g. with .str.extract() df.with_columns(after = pl.col("url").str.extract(r"\?(.*)"))  shape: (1, 2) ┌────────────────────────────────────┬──────────────┐ │ url ┆ after │ │ --- ┆ --- │ │ str ┆ str │ ╞════════════════════════════════════╪══════════════╡ │ https://тестword.com/?foo=bar&id=1 ┆ foo=bar&id=1 │ └────────────────────────────────────┴──────────────┘  .str.splitn() could be another option. df = pl.DataFrame({ "url": ["https://тестword.com/?foo=bar&id=1"] }) df.with_columns( pl.col("url").str.splitn("?", 2) .struct.rename_fields(["before", "after"]) .struct.unnest() )  shape: (1, 3) ┌────────────────────────────────────┬───────────────────────┬──────────────┐ │ url ┆ before ┆ after │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str │ ╞════════════════════════════════════╪═══════════════════════╪══════════════╡ │ https://тестword.com/?foo=bar&id=1 ┆ https://тестword.com/ ┆ foo=bar&id=1 │ └────────────────────────────────────┴───────────────────────┴──────────────┘  It returns a Struct which we rename/unnest into columns.  .struct.rename_fields() .struct.unnest()
Question: I want to split the dataframe according to the sublists that given from diving a list into parts where the only value above a cutoff is the first. e.g. Cutoff = 3 [4,2,3,5,2,1,6,7] => [4,2,3], [5,2,1], [6], [7] I still need to keep track of the other fields in the dataframe. I should get the given result from this df data = { "uid": ["Alice", "Bob", "Charlie"], "time_deltas": [ [4,2, 3], [1,1, 4, 8, 3], [1,1, 7, 3, 2], ], "other_field": [["x", "y", "z"], ["x", "y", "z", "x", "y"], ["x", "y", "z", "x", "y"]] } df = pl.DataFrame(data) cutoff = 3 # Split the time_delta column into lists where the maximum time_delta (excluding the first value) is greater than the cutoff. Ensure that the other_field column is also split accordingly. # Expected Output # +--------+----------------------+----------------------+ # | uid | time_deltas | other_field | # | --- | --- | --- | # | str | list[duration[ms]] | list[str] | # +--------+----------------------+----------------------+ # | Alice | [4, 2, 3] | ["x", "y", "z"] | # | Bob | [1, 1] | ["x", "y"] | # | Bob | [4] | ["z"] | # | Bob | [8, 3] | ["x", "y"] | # | Charlie| [1, 1] | ["x", "y"] | # | Charlie| [7,3,2] | ["z", "x", "y"] | 

Answer: If you explode/flatten the lists, you can use .cum_sum() of the comparison .over() each "group" to assign a group id/index to identify each sublist. (df.explode("time_deltas", "other_field") .with_columns(bool = pl.col("time_deltas") > cutoff) .with_columns(index = pl.col("bool").cum_sum().over("uid")) )  shape: (13, 5) ┌─────────┬─────────────┬─────────────┬───────┬───────┐ │ uid ┆ time_deltas ┆ other_field ┆ bool ┆ index │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ i64 ┆ str ┆ bool ┆ u32 │ ╞═════════╪═════════════╪═════════════╪═══════╪═══════╡ │ Alice ┆ 4 ┆ x ┆ true ┆ 1 │ │ Alice ┆ 2 ┆ y ┆ false ┆ 1 │ │ Alice ┆ 3 ┆ z ┆ false ┆ 1 │ │ Bob ┆ 1 ┆ x ┆ false ┆ 0 │ │ Bob ┆ 1 ┆ y ┆ false ┆ 0 │ │ Bob ┆ 4 ┆ z ┆ true ┆ 1 │ │ Bob ┆ 8 ┆ x ┆ true ┆ 2 │ │ Bob ┆ 3 ┆ y ┆ false ┆ 2 │ │ Charlie ┆ 1 ┆ x ┆ false ┆ 0 │ │ Charlie ┆ 1 ┆ y ┆ false ┆ 0 │ │ Charlie ┆ 7 ┆ z ┆ true ┆ 1 │ │ Charlie ┆ 3 ┆ x ┆ false ┆ 1 │ │ Charlie ┆ 2 ┆ y ┆ false ┆ 1 │ └─────────┴─────────────┴─────────────┴───────┴───────┘  If uid is not unique, you could .with_row_index() first before exploding and use that in the .over() You can then use .group_by() to reassmble the lists. (df.explode("time_deltas", "other_field") .with_columns(index = (pl.col("time_deltas") > cutoff).cum_sum().over("uid")) .group_by("index", "uid", maintain_order=True) .all() )  shape: (6, 4) ┌───────┬─────────┬─────────────┬─────────────────┐ │ index ┆ uid ┆ time_deltas ┆ other_field │ │ --- ┆ --- ┆ --- ┆ --- │ │ u32 ┆ str ┆ list[i64] ┆ list[str] │ ╞═══════╪═════════╪═════════════╪═════════════════╡ │ 1 ┆ Alice ┆ [4, 2, 3] ┆ ["x", "y", "z"] │ │ 0 ┆ Bob ┆ [1, 1] ┆ ["x", "y"] │ │ 1 ┆ Bob ┆ [4] ┆ ["z"] │ │ 2 ┆ Bob ┆ [8, 3] ┆ ["x", "y"] │ │ 0 ┆ Charlie ┆ [1, 1] ┆ ["x", "y"] │ │ 1 ┆ Charlie ┆ [7, 3, 2] ┆ ["z", "x", "y"] │ └───────┴─────────┴─────────────┴─────────────────┘
Question: I have created the following pandas dataframe: import pandas as pd ds = {'col1' : ['A','A','B','C','C','D'], 'col2' : ['A','B','C','D','D','A']} df = pd.DataFrame(data=ds)  The dataframe looks like this: print(df) col1 col2 0 A A 1 A B 2 B C 3 C D 4 C D 5 D A  The possible values in col1 and col2 are A, B, C and D. I need to create 4 new columns, called:  countA: it counts how many A are in each row / record countB: it counts how many B are in each row / record countC: it counts how many C are in each row / record countD: it counts how many D are in each row / record  So, from the example above, the resulting dataframe would look like this:  Can anyone help me please?

Answer: Here is a way using pd.get_dummies() df.join(pd.get_dummies(df,prefix='',prefix_sep='').T.groupby(level=0).sum().T.rename('count{}'.format,axis=1))  and here is a way using value_counts() df.join(df.stack().groupby(level=0).value_counts().unstack(fill_value = 0).rename('count{}'.format,axis=1))  Output:  col1 col2 countA countB countC countD 0 A A 2 0 0 0 1 A B 1 1 0 0 2 B C 0 1 1 0 3 C D 0 0 1 1 4 C D 0 0 1 1 5 D A 1 0 0 1
Question: The following works fine: conn = psycopg.connect(self.conn.params.conn_str) cur = conn.cursor() cur.execute(""" SELECT 2, %s; """, (1,), )  But inside a DO: cur.execute(""" DO $$ BEGIN SELECT 2, %s; END$$; """, (1,), )  it causes psycopg.errors.UndefinedParameter: there is no parameter $1 LINE 1: SELECT 2, $1 ^ QUERY: SELECT 2, $1 CONTEXT: PL/pgSQL function inline_code_block line 3 at SQL statement  Is this expected?

Answer: import psycopg from psycopg import sql con = psycopg.connect("postgresql://postgres:postgres@127.0.0.1:5432/test") cur = con.cursor() cur.execute(sql.SQL(""" DO $$ BEGIN PERFORM 2, {}; END$$; """).format(sql.Literal(1)) )  This uses the sql module of psycopg to build a dynamic SQL statement using proper escaping. DO can't return anything so you will not get any result from the function.
Question: I am using matplotlib to plot the columns of a matrix as separate rectangles using matplotlib.patches.Rectangle. Somehow, all the "inner" lines are wider than the "outer" lines? Does somebody know what's going on here? Is this related to this Github issue? Here's an MRE: import numpy as np import matplotlib.pyplot as plt import seaborn as sns import matplotlib.patches as patches # set seed np.random.seed(42) # define number of cols and rows num_rows = 5 num_cols = 5 # define gap size between matrix columns column_gap = 0.3 # define linewidth linewidth = 5 # Determine the width and height of each square cell cell_size = 1 # Set the side length for each square cell # Initialize the matrix matrix = np.random.rand(num_rows, num_cols) # Create the plot fig, ax = plt.subplots(figsize=(8,6)) # Create a seaborn color palette (RdYlBu) and reverse it palette = sns.color_palette("RdYlBu", as_cmap=True).reversed() # Plot each cell individually with column gaps for i in range(num_rows): for j in range(num_cols): # Compute the color for the cell color = palette(matrix[i, j]) if column_gap > 0: edgecolor = 'black' else: edgecolor = None # Add a rectangle patch with gaps only in the x-direction rect = patches.Rectangle( (j * (cell_size + column_gap), i * cell_size), # x position with gap applied to columns only cell_size, # width of each cell cell_size, # height of each cell facecolor=color, edgecolor=edgecolor, linewidth=linewidth ) ax.add_patch(rect) if column_gap > 0: # Remove the default grid lines and ticks ax.spines[:].set_visible(False) # Set axis limits to fit all cells ax.set_xlim(0, num_cols * (cell_size + column_gap) - column_gap) ax.set_ylim(0, num_rows * cell_size) # Disable x and y ticks ax.set_xticks([]) ax.set_yticks([]) fig.show()  which produces: 

Answer: Your rectangles' edges are getting clipped by the axis boundaries. Add clip_on=False to Rectangle:  rect = patches.Rectangle( (j * (cell_size + column_gap), i * cell_size), # x position with gap applied to columns only cell_size, # width of each cell cell_size, # height of each cell facecolor=color, edgecolor=edgecolor, linewidth=linewidth, clip_on=False, )  Output (small size for the demo):  To better see what's going on, let's add some transparency to your rectangles and change the axis background color: ax.patch.set_facecolor('red')
Question: Poetry has the version command to increment a package version. Does uv package manager has anything similar?

Answer: Currently uv package manager does not have a built-in command to bump package versions like poetry's version command. You can manually edit pyproject.toml or automate it with a script. For example: import toml from typing import Literal def bump_version(file_path: str, part: Literal["major", "minor", "patch"] = "patch") -> None: with open(file_path, "r") as f: pyproject = toml.load(f) version = pyproject["tool"]["poetry"]["version"] major, minor, patch = map(int, version.split(".")) if part == "major": major += 1 minor = 0 patch = 0 elif part == "minor": minor += 1 patch = 0 elif part == "patch": patch += 1 else: raise ValueError("Invalid part value. Choose 'major', 'minor', or 'patch'.") pyproject["tool"]["poetry"]["version"] = f"{major}.{minor}.{patch}" with open(file_path, "w") as f: toml.dump(pyproject, f) print(f"Version bumped to {major}.{minor}.{patch}")
Question: Say I have data = {'id': [1, 1, 1, 2, 2, 2], 'd': [1, 2, 3, 1, 2, 3], 'sales': [1, 4, 2, 3, 1, 2]}  I want to compute a rolling sum with window of 2 partitioned by 'id' ordered by 'd' Using SQL I can do: duckdb.sql(""" select *, sum(sales) over w as rolling_sales from df window w as (partition by id order by d rows between 1 preceding and current row) """) Out[21]: ┌───────┬───────┬───────┬───────────────┐ │ id │ d │ sales │ rolling_sales │ │ int64 │ int64 │ int64 │ int128 │ ├───────┼───────┼───────┼───────────────┤ │ 1 │ 1 │ 1 │ 1 │ │ 1 │ 2 │ 4 │ 5 │ │ 1 │ 3 │ 2 │ 6 │ │ 2 │ 1 │ 3 │ 3 │ │ 2 │ 2 │ 1 │ 4 │ │ 2 │ 3 │ 2 │ 3 │ └───────┴───────┴───────┴───────────────┘  This works great, but how can I do it using the Python Relational API? I've got as far as rel = duckdb.sql('select * from df') rel.sum( 'sales', projected_columns='*', window_spec='over (partition by id order by d rows between 1 preceding and current row)' )  which gives ┌───────────────────────────────────────────────────────────────────────────────────────┐ │ sum(sales) OVER (PARTITION BY id ORDER BY d ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) │ │ int128 │ ├───────────────────────────────────────────────────────────────────────────────────────┤ │ 3 │ │ 4 │ │ 3 │ │ 1 │ │ 5 │ │ 6 │ └───────────────────────────────────────────────────────────────────────────────────────┘  This is close, but it's not quite right - how do I get the name of the last column to be rolling_sales?

Answer: I'm not an expert in DuckDB relational API but this works: rel.sum( 'sales', projected_columns='*', window_spec='over (partition by id order by d rows between 1 preceding and current row) as rolling_sales' )  ┌───────┬───────┬───────┬───────────────┐ │ id │ d │ sales │ rolling_sales │ │ int64 │ int64 │ int64 │ int128 │ ├───────┼───────┼───────┼───────────────┤ │ 1 │ 1 │ 1 │ 1 │ │ 1 │ 2 │ 4 │ 5 │ │ 1 │ 3 │ 2 │ 6 │ │ 2 │ 1 │ 3 │ 3 │ │ 2 │ 2 │ 1 │ 4 │ │ 2 │ 3 │ 2 │ 3 │ └───────┴───────┴───────┴───────────────┘
Question: I have a pygame mask of a text surface that I would like to invert, in the sense that the black becomes white, and the white becomes black. The black is the transparent part of the text, and the white is the non-transparent part, but I'd like it flipped so I can make a text outline. I can't really figure it out. If anyone knows, it would be much appreciated Ill attach the code that generates and blits the mask :)  location_text = self.font.render(self.location, True, self.text_color) pos = ((screen_width - location_text.get_width()) / 2, 320) mask = pygame.mask.from_surface(location_text) mask_surf = mask.to_surface() mask_surf.set_colorkey((0, 0, 0)) screen.blit(mask_surf, (pos[0], pos[1]))  

Answer: There are different possibilities. You can invert the mask with invert. mask = pygame.mask.from_surface(location_text) mask.invert() mask_surf = mask.to_surface() mask_surf.set_colorkey((255, 255, 255))  You can also set the colors when you turn the mask into a surface. Make the setcolor black and the unsetcolor white (see to_surface()): mask = pygame.mask.from_surface(location_text) mask_surf = mask.to_surface(setcolor=(0, 0, 0, 0), unsetcolor=(255, 255, 255, 255))
Question: Is a lock necessary in a situation where thread 1 checks if a bool has flipped from False to True periodically within a loop, the bool being updated in thread 2? As I understand a bool is atomic in python, it should not be possibly for the bool to be incorrectly updated or take on a garbage value like in C++ for example. Only one thread will ever update the bool, and it will only ever go from False to True (there is no position where it switches back to False). As the check is done periodically and timing is not critical, even if thread 1 reads the old value (False) while thread 2 is updating it to True, thread 1 should still be able to read the new value once thread 2 has finished on the next iteration of the loop. Is this an incorrect understanding of this specific situation? I understand it is generally best to use locks, and I don't mind adding one, but I wonder if it would actually just be introducing more potential problems (like deadlocks) without actually solving any problem except maybe saving thread 1 from looping for one more iteration. This is the loop in question. The two variables are being updated in another thread, and read in this one. Both are bool values starting as False and being set to True when the other threads have finished.  while True: time.sleep(0.2) if self.joined_queries: self.stop() break if self.timeout: self.stop() break  There were some other threads but the answers were very general without going into specifics much, and the situation was a bit different. I would like to understand why this is a bad idea or not! This piece of documentation makes me believe it is not a problem, but I am not really sure if I am interpreting it correctly: http://www.python.org/doc/faq/library/#what-kinds-of-global-value-mutation-are-thread-safe

Answer:  As I understand a bool is atomic in python, it should not be possibly for the bool to be incorrectly updated or take on a garbage value like in C++ for example  Practically, a bool variable in cPython is going to be a pointer to one of the two objects Py_True or Py_False. The implementation details shouldn't matter, but it's relevant to know that a bool in Python will be exactly as atomic as a pointer in C. In a cPython build without the GIL, this will be a data race and hence Undefined Behaviour according to the underlying C code.  This piece of documentation makes me believe it is not a problem  The page you linked explicitly says both that this sort of code is safe due to the GIL, and that work on removing the GIL to improve performance is ongoing. It seems unwise to write new code that depends on it. Note that C's Undefined Behaviour may be perfectly well-defined on a given hardware platform, it's just non-portable. However, the code will be brittle in the face of newer interpreters and platforms.
Question: I am trying to solve a problem in my data-frame df.head() 0 Key value 1 10 500 2 11 500 3 12 600 4 12 800 5 13 1000 6 13 1200 . . . 200++  output is to put the values in the above data-frame or have another data-frame with all the values of above with additional info show as below. Expected Output: 0 Key value 1 10 500 2 11 500 3 12 600 4 12 800 5 12 1400 -----> Addition of 800+600 as keys are same 6 13 1000 7 13 1200 8 13 2200 -----> Addition of 1000+12000 as keys are same . . 200++  I am just starting out in Pandas, any help will be appreciate.

Answer: A possible solution, which takes the following steps:  First, groupby is used to organize df by Key, and then filter is applied with a lambda function that selects only groups with more than one row, ensuring sums are computed only for repeated Key values.  Next, this filtered group is re-aggregated with groupby to calculate the sum of value within each group of Key values using sum. The concatenated dataframe is then organized by Key and value columns through sort_values, with ignore_index=True to reset indexing.   (pd.concat([ df, df.groupby('Key').filter(lambda x: len(x) > 1) .groupby('Key', as_index=False)['value'].sum()]) .sort_values('Key', ignore_index=True))   Another possible solution: pd.concat( [df, df.groupby('Key', as_index=False)['value'] .apply(lambda x: None if len(x) == 1 else sum(x)) .dropna()]).sort_values('Key', ignore_index=True)   Output:  Key value 0 10 500 1 11 500 2 12 600 3 12 800 4 12 1400 5 13 1000 6 13 1200 7 13 2200
Question: I want to know if there's a way to show an indicator or something that tells me at which line my Jupyter Lab code is while executing. Google Colab does this with a little green arrow next to the line (see image below), and I'm wondering if there's something similar for JL. 

Answer: Not quite like the way that corporation adapted the open source product, but some of these options may get you to what you want.... JupyterLab lets you attach a console to monitor everything as it runs. You want to make show you activate Show All Kernel Activity. See here, here, and here. See more about JupyterLab's code console in the documentation here. Now that doesn't quite still do what you want, but you can add a shortcut that lets you specify lines to run to allow you to narrow the running code to what you specify. See 'Feature Request - Ability to Split and Independently Execute Sections of a Single Cell'. Alternatively... It's not the same thing, but related. You can use the Visual Debugger built into JupyterLab to step through the callstack after you set at least one breakpoint. It will show the variable values as they change. See here for more about how it relates to what you'd like to do, and the official documentation for the Visual Debugger is here.  Documenting related posts beyond references in this reply:  Jupyter Discourse post 'Line currently being executed' (Nothing posted there at this time but maybe it will be updated down the line...)  Also Related:  'How to run a single line or selected code in a Jupyter Notebook or JupyterLab cell?' 'Feature Request - Ability to Split and Independently Execute Sections of a Single Cell' There's also a log console, see here.
Question: I'm stuck in a Jinja implementation problem. Here is my little python script: path = Path(__file__).parent env = Environment( loader=FileSystemLoader(path / "templates") ) template = env.get_template("template1.rst") rendered = template.render(sample={"a": {"b": "c"}})  And here is my template for jinja: .. toctree:: :maxdepth: 3 {% for k, v in sample.items() recursive %} - {{ k }}: {%- if v is string %} {{ v }} {%- else %} {{ loop(v) }} {%- endif -%} {%endfor%}  The execution returns this error: File "/home/jaja/Bureau/coding/bac_a_sable/sphinx_test/templates/template1.rst", line 5, in top-level template code {% for k, v in sample.items() recursive %} ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/jaja/Bureau/coding/bac_a_sable/sphinx_test/templates/template1.rst", line 21, in template {{ loop(v) }} ^^^^^^^^^^^^^^^^^^ File "/home/jaja/Bureau/coding/bac_a_sable/sphinx_test/templates/template1.rst", line 5, in template {% for k, v in sample.items() recursive %} ^^^^^^^^^^^^^^^^^^^^^^^^^ ValueError: not enough values to unpack (expected 2, got 1)  As the v value of first loop is {"b": "c"}, it must work, but it doesn't. Is Jinja unable to recursively loop in dictionaries ?

Answer: immediate fix When you start the loop, you use sample.items() iterator - {% for k, v in sample.items() recursive %} ^^^^^^^^^^^^^^  When you recur, you are passing the dict itself -  {%- else %} {{ loop(v) }} ^  Simply change this to -  {%- else %} {{ loop(v.items()) }} ^^^^^^^^^   naive test An improvement to the entire loop would be to change the test to mapping, instead of string. {% for k, v in sample.items() recursive %} - {{ k }}: {%- if v is mapping %} {{ loop(v.items()) }} {%- else %} {{ v }} {%- endif -%} {%endfor%}  This ensures that you only recur on dicts. In the original code, the else will recur any non-string input. If the data included a number, you would've encountered a different error.  nested input, nested output Preserving the levels of nesting in the output can be challenging. Consider using the loop.depth helper to create the correct whitespace - {% for k, v in sample.items() recursive %} {{ " " * (loop.depth - 1) }}- {{ k }}: {%- if v is mapping %} {{- loop(v.items()) }} {%- else %} {{ v }} {%- endif -%} {%endfor%}  Given sample input - sample = { 'a': { 'b': 1, 'c': { 'd': 2 }, 'e': 'f', }, }  Output - a: - c: - d: 2 - b: 1 - e: f