eshangj/stackoverflow_q_and_a_sample huggingface dataset:
Question: I tried to create a simple single-linked list as the following: class node: def __init__(self, data=None): self.data = data self.next = None class linkedlist: def __init__(self): self.head = node() def append(self, data): curr = self.head new_node = node(data) while curr.next != None: curr = curr.next curr.next = new_node def total(self): curr = self.head total = 0 while curr.next != None: curr = curr.next total += 1 return total def display(self): # added total here as well curr = self.head em = [] total = 0 while curr.next != None: curr = curr.next em.append(curr.data) total += 1 print(f"LinkedList: {em} \n Total: {self.total()} ") def look(self, index): if index >= self.total(): print("ERROR: Index error" ) curr_index = self.head idx = 0 while True: curr_index = curr_index.next if idx == index: print(curr_index.data) idx += 1  Whenever I am calling the look() function, I am getting the following error: curr_index = curr_index.next ^^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'next'  What could this mean? As far as I know, the curr_index is using the self.head, which is inturn using node(). The node() have does have the next attribute. This error isn't there when I call the other functions in the class. Moreover, the other functions -- except the look() function -- returns their respective values error-free. Where is my code going wrong?

Answer: In this implementation, each node point to the next node of the list, and the last one points to None, signifying that's the end of the list. The loop in look tries to iterate over the nodes until it gets to the indexth item and then prints it, but the loop is not terminated there. In fact, it will continue indefinitely until at some point it passes the last element, making the current item None, and then fail with this error. One approach is to explicitly terminate the loop once you've reached the desired element: def look(self, index): if index >= self.total(): # Need to throw here, not just print # because printing out an error won't prevent the function from moving on throw ValueError("ERROR: Index error") curr_index = self.head idx = 0 while True: curr_index = curr_index.next if idx == index: print(curr_index.data) return # We're done here, return idx += 1  Having said that, checking idx == index on each iteration is superfolous. You could just advance curr_index index times explicitly: def look(self, index): if index >= self.total(): # Need to throw here, not just print # because printing out an error won't prevent the function from moving on throw ValueError("ERROR: Index error") curr_index = self.head for _ in range(index): curr_index = curr_index.next print(curr_index.data)
Question: I have a Pandas DataFrame, as defined here: df = pd.DataFrame({'Name': ['Alice', 'Bob', 'Aritra'], 'Age': [25, 30, 35], 'Location': ['Seattle', 'New York', 'Kona']}, index=([10, 20, 30]))  However, when I index into this DataFrame, I can't accurately predict what type of object is going to result from the indexing: # (1) str df.iloc[0, df.columns.get_loc('Name')] # (2) Series df.iloc[0:1, df.columns.get_loc('Name')] # (3) Series df.iloc[0:2, df.columns.get_loc('Name')] # (4) DataFrame df.iloc[0:2, df.columns.get_loc('Name'):df.columns.get_loc('Age')] # (5) Series df.iloc[0, df.columns.get_loc('Name'):df.columns.get_loc('Location')] # (6) DataFrame df.iloc[0:1, df.columns.get_loc('Name'):df.columns.get_loc('Location')]  Note that each of the pairs above contain the same data. (e.g. (2) is a Series that contains a single string, (4) is a DataFrame that contains a single column, etc.) Why do they output different types of objects? How can I predict what type of object will be output? Given the data, it looks like the rule is based on how many slices (colons) you have in the index:  0 slices ((1)): scalar value 1 slice ((2), (3), (5)): Series 2 slices ((4), (6)): DataFrame  However, I'm not sure if this is always true, and even if it is always true, I want to know the underlying mechanism as to why it is like that. I've spent a while looking at the indexing documentation, but it doesn't seem to describe this behavior clearly. The documentation for the iloc function also doesn't describe the return types. I'm also interested in the same question for loc instead of iloc, but, since loc is inclusive, the results aren't quite as bewildering. (That is, you can't get pairs of indexes with different types where the indexes should pull out the exact same data.)

Answer: You got the general idea. To make it simple, what matter is not the number of items but the type of indexer. You can index as 0D (with a scalar), let's just consider the index for now: df.iloc[0] df.loc[0]  or 1D (with a slice or iterable): df.loc[[0]] df.loc[1:2] df.loc[:0]  Then the rule is simple, consider both axes, if both are 0D you get a scalar (here a string), if both are 1D you get a DataFrame, else a Series: columns 0D 1D index 0D scalar Series 1D Series DataFrame  Some examples to illustrate this: type(df.iloc[1:2, 1:2]) # 1D / 1D # pandas.core.frame.DataFrame type(df.iloc[:0, :0]) # 1D / 1D # pandas.core.frame.DataFrame (EMPTY DataFrame) type(df.iloc[[], []]) # 1D / 1D # pandas.core.frame.DataFrame (EMPTY DataFrame) type(df.iloc[[1,2], 0]) # 1D / 0D # pandas.core.series.Series type(df.iloc[0, [0]]) # 0D / 1D # pandas.core.series.Series type(df.iloc[0, 0]) # 0D / 0D # str
Question: I am trying to read word documents using Python. However, I am stuck in places where the document is password protected, as I do not have the password for the file(s). How can I detect if the file has password, so can I ignore such files from opening? Currently, the below code opens a dialog/prompt window in MS-Word to enter the password and keeps waiting for a response. word = win32.gencache.EnsureDispatch('Word.Application') doc = word.Documents.Open(r"D:\appointment\PasswordProtectedDoc.doc") 

Answer: Well I figured out the answer myself. Passed a wrong password as a parameter and it raised an exception saying Invalid/Incorrect password which I can handle it in a try except block. Little strange but works well. word = win32.gencache.EnsureDispatch('Word.Application') word.Visible = False try: doc = word.Documents.Open(r"D:\appointment\PasswordProtectedDoc.doc",PasswordDocument='ddd') doc.Activate () except: print(f"Failed to open") finally: word.Quit()
Question: I am doing my first CI project and I have recently got confused about artefacts... Say I have config with next jobs: cleanup_build: tags: - block_autotest stage: cleanup script: - Powershell $env:P7_TESTING_INSTALLATION_PATH\client\p7batch.exe --log-level=error --run $env:JOBS_FOLDER_PATH\clear.py install_block: tags: - block_autotest stage: installation script: - Powershell $env:P7_TESTING_INSTALLATION_PATH\client\p7batch.exe --log-level=error --run $env:JOBS_FOLDER_PATH\setup_block.py  "install_block" job is not to be done if the job "cleanup_build" has failed. So, I have to create some kind of artifact after "cleanup_build" has succeeded so this artefact is visible at the stage "installation" for the job "install_block". At the job "install_block" I could use python to address the artifact and ensure the one exists. Also I have created a speciad folder for artifacts: ARTEFACTS_FOLDER_PATH: $CI_PROJECT_DIR\autotest\artefacts  So within the job "cleanup_build" I create a file "clean" at the artefact folder. But it seems that CI reloads repository at project directory, because if I leave just "cleanup_build" job (delete "install_block" from yml) I can see the "clean" file at the project, but if I leave both jobs this file dissapears before "install_block" job begins...

Answer: By default, every job starts with a 'clean' workspace. If one job modifies the workspace, it is not persisted into any other job. To pass files between jobs, you must explicitly declare artifacts to be passed between each job. Also note that the aritfact path is relative to the workspace root. stages: - one - two my_job: stage: one script: - echo "change" > myfile.txt artifacts: paths: # this must be a relative path, not absolute! - myfile.txt my_next_job: stage: two script: # or use 'type' instead of 'cat' on Windows - cat myfile.txt  When the job with artifacts: defined completes, you will see a message at the end of the job log indicating the number of matched/uploaded artifacts. Also note that, by default, if a job fails, subsequent jobs will not run. That is: the when: behavior is on_success by default. You can enable to jobs to run additionally (or only) on failures by using when: always (or when: on_failure).
Question: Here is an R example of using Reduce x <- c(1, 2, 2, 4, 10, 5, 5, 7) Reduce(\(a, b) if (tail(a, 1) != b) c(a, b) else a, x) # equivalent to `rle(x)$values`  The code above is to sort out the extract unique values in terms of run length, which can be easily obtained by rle(x)$values.  I know in Python there is itertools.groupby that performs the same thing as rle in R, BUT, what I am curious about is: Is it possible to have a highly similar translation by using functools.reduce in Python to achieve the same functionality, say, for example from functools import reduce x = [1,2,2,4,10,5,5,7] reduce(lambda a, b: a + [b] if a[-1]!= b else a, x)  but which unfortunately gives errors like { "name": "TypeError", "message": "'int' object is not subscriptable", "stack": "--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[58], line 4 1 from functools import reduce 2 x = [1,2,2,4,10,5,5,7] ----> 4 reduce(lambda a, b: a + [b] if a[-1]!= b else a, x) Cell In[58], line 4, in <lambda>(a, b) 1 from functools import reduce 2 x = [1,2,2,4,10,5,5,7] ----> 4 reduce(lambda a, b: a + [b] if a[-1]!= b else a, x) TypeError: 'int' object is not subscriptable" }   My question is: Is there any one-liner of reduce in Python that looks like R code?

Answer: you could use a list as the initial: from functools import reduce x = [1,2,2,4,10,5,5,7] reduce(lambda a, b: a + [b] if a[-1]!= b else a, x, [x[0]]) [1, 2, 4, 10, 5, 7]   Note that you could use groupby from itertools:   from itertools import groupby [i for i,j in groupby(x)] [1, 2, 4, 10, 5, 7]
Question: A contains columns x, y1, y2, y3 & y4. I am interested in studying the {y1,y2,y3,y4} sequence w.r.t x. To find unique {y1,y2,y3,y4} sequence occurring for each x, I do the following: B = pd.DataFrame() for x_temp in A['x'].unique(): B = pd.concat([B, A[A['x'] == x_temp][['x','y1','y2','y3','y4']]]) B = B.drop_duplicates().sort_values(by=['x','y1','y2','y3','y4']) del x_temp  I want to introduce a new column called 'count' in B, which contains # of unique {y1,y2,y3,y4} that occurred for that specific x in A. B['count'] = A.apply(lambda row: (A['y1'] == row['y1']) & (A['y2'] == row['y2']) & (A['y3'] == row['y3']) & (A['y4'] == row['y4']), axis=1).sum()  This works, however, it doesn't work if A or B has missing values. I want it to treat missing values also as a unique value. Example: A = pd.DataFrame({'x':['1','1','1','1','2','2','2','2','2','1'], 'y1':['1','2','2',np.nan,'2',np.nan,'2','2','2','1'], 'y2':['2','1','2','2',np.nan,np.nan,'2','2','1','2'], 'y3':['1','1',np.nan,'2',np.nan,'2',np.nan,np.nan,'1','1'], 'y4':['2','2','2',np.nan,np.nan,'1','2','2','2','2']}) B = pd.DataFrame() for x_temp in A['x'].unique(): B = pd.concat([B, A[A['x'] == x_temp][['x','y1','y2','y3','y4']]]) B = B.drop_duplicates().sort_values(by=['x','y1','y2','y3','y4']) del x_temp B['count'] = A.apply(lambda row: (A['y1'] == row['y1']) & (A['y2'] == row['y2']) & (A['y3'] == row['y3']) & (A['y4'] == row['y4']), axis=1).sum() print(B) x y1 y2 y3 y4 count 0 1 1 2 1 2 2 1 1 2 1 1 2 2 2 1 2 2 NaN 2 0 3 1 NaN 2 2 NaN 0 8 2 2 1 1 2 2 6 2 2 2 NaN 2 0 4 2 2 NaN NaN NaN 0 5 2 NaN NaN 2 1 0 

Answer: Assuming you want to count the values and then get the sum across the different xs, you could use: cols = ['x','y1','y2','y3','y4'] out = (A[cols].value_counts(dropna=False, sort=False) .reset_index(name='count') .sort_values(by=cols, na_position='last') .assign(count=lambda x: x.groupby(cols[1:], dropna=False) ['count'].transform('sum') ) )  Output:  x y1 y2 y3 y4 count 0 1 1 2 1 2 2 1 1 2 1 1 2 2 2 1 2 2 NaN 2 3 3 1 NaN 2 2 NaN 1 4 2 2 1 1 2 2 5 2 2 2 NaN 2 3 6 2 2 NaN NaN NaN 1 7 2 NaN NaN 2 1 1  If you want to set the rows with NaNs as 0: cols = ['x','y1','y2','y3','y4'] out = (A[cols].value_counts(dropna=False, sort=False) .reset_index(name='count') .sort_values(by=cols, na_position='last') .assign(count=lambda x: x.groupby(cols[1:]) ['count'].transform('sum') .fillna(0).convert_dtypes() ) )  Output:  x y1 y2 y3 y4 count 0 1 1 2 1 2 2 1 1 2 1 1 2 2 2 1 2 2 NaN 2 0 3 1 NaN 2 2 NaN 0 4 2 2 1 1 2 2 5 2 2 2 NaN 2 0 6 2 2 NaN NaN NaN 0 7 2 NaN NaN 2 1 0  If you don't want to sum across the xs: cols = ['x','y1','y2','y3','y4'] out = (A[cols].value_counts(dropna=False, sort=False) .reset_index(name='count') .sort_values(by=cols, na_position='last') )  Output:  x y1 y2 y3 y4 count 0 1 1 2 1 2 2 1 1 2 1 1 2 1 2 1 2 2 NaN 2 1 3 1 NaN 2 2 NaN 1 4 2 2 1 1 2 1 5 2 2 2 NaN 2 2 6 2 2 NaN NaN NaN 1 7 2 NaN NaN 2 1 1
Question: This is my DataFrame: import pandas as pd df = pd.DataFrame( { 'start': [3, 11, 9, 19, 22], 'end': [10, 17, 10, 25, 30] } )  And expected output is creating column x:  start end x 0 3 10 10 1 11 17 17 2 9 10 NaN 3 19 25 25 4 22 30 NaN  Logic: I explain it row by row. For row 0, x is df.end.iloc[0]. Now this value of x needs to be preserved until a greater value is found in the next rows and in the start column. So 10 should be saved then the process moves to row 1. Is 11 > 10? If yes then x of second row is 17. For the next row, Is 9 > 17? No so the value is NaN. The process moves to next row. Since no values is found that is greater than 17, 17 is preserved. Is 19 > 17? Yes so x is set to 25. And for the last row since 22 < 25, NaN is selected. I have provided additional examples with different df and the desired outputs: df = pd.DataFrame({'start': [3, 20, 11, 19, 22],'end': [10, 17, 21, 25, 30]}) start end x 0 3 10 10.0 1 20 17 17.0 2 11 21 NaN 3 19 25 25.0 4 22 30 NaN df = pd.DataFrame({'start': [3, 9, 11, 19, 22],'end': [10, 17, 21, 25, 30]}) start end x 0 3 10 10.0 1 9 17 NaN 2 11 21 21.0 3 19 25 NaN 4 22 30 30.0 df = pd.DataFrame({'start': [3, 11, 9, 19, 22],'end': [10, 17, 21, 25, 30]}) start end x 0 3 10 10.0 1 11 17 17.0 2 9 21 NaN 3 19 25 25.0 4 22 30 NaN  This gives me the result. Is there a vectroized way to do this? l = [] for ind, row in df.iterrows(): if ind == 0: x = row['end'] l.append(x) continue if row['start'] > x: x = row['end'] l.append(x) else: l.append(np.NaN) 

Answer: updated answer If the previous end should be propagated, then the logic cannot be vectorized. However, it is possible to be much faster than iterrows using numba: from numba import jit @jit(nopython=True) def f(start, end): prev_e = -np.inf out = [] for s, e in zip(start, end): if s>prev_e: out.append(e) prev_e = e else: out.append(None) return out df['x'] = f(df['start'].to_numpy(), df['end'].to_numpy())  Output: # example 1 start end x 0 3 10 10.0 1 11 17 17.0 2 9 10 NaN 3 19 25 25.0 4 22 30 NaN # example 2 start end x 0 3 10 10.0 1 20 17 17.0 2 11 21 NaN 3 19 25 25.0 4 22 30 NaN # example 3 start end x 0 3 10 10.0 1 9 17 NaN 2 11 21 21.0 3 19 25 NaN 4 22 30 30.0 # example 4 start end x 0 3 10 10.0 1 11 17 17.0 2 9 21 NaN 3 19 25 25.0 4 22 30 NaN  original answer IIUC, you could use shift to form a boolean mask and mask to hide the non-valid values: df['x'] = df['end'].mask(df['start'].le(df['end'].shift()))  The trick here is to compare start <= end.shift, which will result in False for the first row because of the NaN. If you want to exclude the first row then you should have used df['end'].where(df['start'].gt(df['end'].shift())). Output:  start end x 0 3 10 10.0 1 11 17 17.0 2 9 10 NaN 3 19 25 25.0 4 22 30 NaN  Intermediates:  start end x end.shift start<=end.shift 0 3 10 10.0 NaN False 1 11 17 17.0 10.0 False 2 9 10 NaN 17.0 True 3 19 25 25.0 10.0 False 4 22 30 NaN 25.0 True
Question: I have a table of content in the form of indention to track the hierarchy like: - title1 -- title1-1 -- title1-2 --- title1-2-1 --- title1-2-2 - title2 -- title2-1 -- title2-2 - title3 - title4  I want to translate them with a numbering format like: 1 title1 1.1 title1-1 1.2 title1-2 1.2.1 title1-2-1 1.2.2 title1-2-2 2 title2 2.1 title2-1 2.2 title2-2 3 title3 4 title4  This is just an example where the string "title-*" could be any heading text. Also the size of an indent could get greater than in this example. This comes from my real work, where I collect headings, or manually hand-written headings, in a Word document and reformat these possible headings from beginning to end aiming to correct any wrong order and indention. I have tried this myself, and while mostly these headings were transformed into the desired format, for some it did not work out. How should this be done?

Answer: You could use the replacer callback of re.sub to implement the logic. In that callback use a stack (that is maintained across multiple replacements) to track the chapter numbers of upper "levels". Code: import re def add_numbers(s): stack = [0] def replacer(s): indent = len(s.group(0)) - 1 del stack[indent+1:] if indent >= len(stack): stack.append(0) stack[indent] += 1 return ".".join(map(str,stack)) return re.sub(r"^-+", replacer, s, flags=re.M)  Here is how you would call it on your example: message_string = """- title1 -- title1-1 -- title1-2 --- title1-2-1 --- title1-2-2 - title2 -- title2-1 -- title2-2 - title3 - title4""" res = add_numbers(message_string) print(res)  This prints: 1 title1 1.1 title1-1 1.2 title1-2 1.2.1 title1-2-1 1.2.2 title1-2-2 2 title2 2.1 title2-1 2.2 title2-2 3 title3 4 title4
Question: I have two DataFrames in polars, one that describes the meta data, and one of the actual data (LazyFrames are used as the actual data is larger): import polars as pl df = pl.LazyFrame( { "ID": ["CX1", "CX2", "CX3"], "Sample1": [1, 1, 1], "Sample2": [2, 2, 2], "Sample3": [4, 4, 4], } ) df_meta = pl.LazyFrame( { "sample": ["Sample1", "Sample2", "Sa,mple3", "Sample4"], "qc": ["pass", "pass", "fail", "pass"] } )  I need to select the columns in df for samples that have passing qc using the information in df_meta. As you can see, df_meta has an additional sample, which of course we are not interested in as it's not part of our data. In pandas, I'd do (not very elegant but does the job): df.loc[:, df.columns.isin(df_meta.query("qc == 'pass'")["sample"])]  However I'm not sure about how doing this in polars. Reading through SO and the docs didn't give me a definite answer. I've tried: df.with_context( df_meta.filter(pl.col("qc") == "pass").select(pl.col("sample").alias("meta_ids")) ).with_columns( pl.all().is_in("meta_ids") ).collect()  Which however raises an exception: InvalidOperationError: `is_in` cannot check for String values in Int64 data  I assume it's checking the content of the columns, but I'm interested in the column names. I've also tried: meta_ids = df_meta.filter(pl.col("qc") == "pass").get_column("sample") df.select(pl.col(meta_ids))  but as expected, an exception is raised as there's one sample not accounted for in the first dataFrame: ColumnNotFoundError: Sample4  What would be the correct way to do this?

Answer: Just to build upon https://stackoverflow.com/a/78676922/ - I find require_all=False rather cryptic. It is also possible to set intersect with the cs.all() selector: >>> meta_ids = df_meta.filter(pl.col("qc") == "pass")["sample"] >>> cs.all() & cs.by_name(meta_ids) (cs.all() & cs.by_name('Sample1', 'Sample2', 'Sample4'))  df.select(cs.all() & cs.by_name(meta_ids))  shape: (3, 2) ┌─────────┬─────────┐ │ Sample1 ┆ Sample2 │ │ --- ┆ --- │ │ i64 ┆ i64 │ ╞═════════╪═════════╡ │ 1 ┆ 2 │ │ 1 ┆ 2 │ │ 1 ┆ 2 │ └─────────┴─────────┘
Question: I want to get the product table data array using the array_agg function. In Postgers, this works great, but in SQLalchemy this can only be done with data types such as integer, strings, and so on. How do I implement this in SQLalchemy? Code in postgresql:  select DISTINCT seller.title, array_agg(product), COUNT(product.id) from seller_product INNER JOIN seller ON seller.ozon_id = seller_product.id_seller INNER JOIN product ON product.ozon_id = seller_product.id_product WHERE start_id = 36 GROUP BY seller.title ORDER BY COUNT(product.id) DESC  Code python. I'm trying to do it like this: slct_stmt_now = select(Seller, func.array_agg(Product.__table__), func.count(Product.id)).distinct().select_from(seller_product) slct_stmt_now = slct_stmt_now.join(Seller, Seller.ozon_id == seller_product.columns["id_seller"]).join(Product, Product.ozon_id == seller_product.columns["id_product"]).where(seller_product.columns["start_id"] == LAST_START_ID).group_by(Seller) now_data_txt = session.execute(slct_stmt_now.order_by(func.count(Product.id).desc())).all() 

Answer: The GitHub discussion that @snakecharmerb cites above includes the comment  relationship does exactly what you are looking for in an object oriented way.  # https://stackoverflow.com/q/78676983/2144390 # fmt: off from sqlalchemy import Column, ForeignKey, Integer, String, Table, create_engine, select from sqlalchemy.orm import Session, declarative_base, joinedload, relationship # fmt: on engine = create_engine("postgresql://scott:tiger@192.168.0.199/test") Base = declarative_base() seller_product = Table( "seller_product", Base.metadata, Column( "id_seller", Integer, ForeignKey("seller.ozon_id"), primary_key=True ), Column( "id_product", Integer, ForeignKey("product.ozon_id"), primary_key=True ), ) class Product(Base): __tablename__ = "product" id = Column(Integer, primary_key=True) ozon_id = Column(Integer, nullable=False) name = Column(String, nullable=True) def __repr__(self): return f"Product({repr(self.name)})" class Seller(Base): __tablename__ = "seller" id = Column(Integer, primary_key=True) ozon_id = Column(Integer, nullable=False) title = Column(String, nullable=True) # using this instead of array_agg() products = relationship("Product", secondary=seller_product) def __repr__(self): return ( f"Seller(title={repr(self.title)}, products={repr(self.products)})" ) engine.echo = True with Session(engine) as sess: a_seller = sess.scalars( select(Seller).options(joinedload(Seller.products)) ).first() """ SELECT seller.id, seller.ozon_id, seller.title, product_1.id AS id_1, product_1.ozon_id AS ozon_id_1, product_1.name FROM seller LEFT OUTER JOIN ( seller_product AS seller_product_1 JOIN product AS product_1 ON product_1.ozon_id = seller_product_1.id_product ) ON seller.ozon_id = seller_product_1.id_seller """ print(a_seller) """ Seller(title='Harbor Freight', products=[Product('wrench'), Product('hammer')]) """
Question: I read in a stored numpy array with dtype object in polars. I want to change column dtype from object to float in the polars dataframe. Minimal example: # generate sample data data = {"1": ["1.0", "2.0", "3.0", "4.0"], "2": [10, 20, 30, 40]} df = pl.DataFrame(data, schema={'1':pl.Object, '2':pl.Object}) # what I want to do df.with_columns(pl.col('2').cast(pl.Float64, strict=False))  The last line yields an error:  polars.exceptions.ComputeError: cannot cast 'Object' type  How can I do this?

Answer: Usually, by the time an object dtype made it into your dataframe, it is already too late to perform any native polars operation on it. Still, you can apply pl.Expr.map_elements to map a user-defined function over elements. df.with_columns( pl.col("1").map_elements(lambda x: x, return_dtype=pl.String), pl.col("2").map_elements(lambda x: x, return_dtype=pl.Int32), )  shape: (4, 2) ┌─────┬─────┐ │ 1 ┆ 2 │ │ --- ┆ --- │ │ str ┆ i32 │ ╞═════╪═════╡ │ 1.0 ┆ 10 │ │ 2.0 ┆ 20 │ │ 3.0 ┆ 30 │ │ 4.0 ┆ 40 │ └─────┴─────┘