eshangj/stackoverflow_q_and_a_sample huggingface dataset:
Question: I want to detect USB on Raspberry Pi and access USB to copy some data. I used pyudev and get some info from USB but I can't access it. What should I do? This is my code: import pyudev context = pyudev.Context() for device in context.list_devices(subsystem='block', DEVTYPE='disk'): for props in device.properties: if device.get("ID_BUS") == "usb": print(props, device.get(props))  The path of the USB is /media/pi/CCCOMA_X64FRE_EN-GB_DV9 but I don't find it in list properties, when I print them out. How can I fix it? Thanks.

Answer: The reason that you can't find the mount point of the usb drive is that device.properties doesn't include the mount point. You could however get the disk name (/dev/sdx) from device.properties and then use subprocess.check_output(['findmnt', '/dev/sdx1', '-no', 'TARGET']) you can find your mount point in the return of this function.
Question: I made category as below. 1~4 : 0 5~9 : 1 10~15 : 2  I have a numpy array as below. np.array([2, 5, 10, 13, 7, 9])  How can I make fastest way to change above numpy array based on given conditioin as below? np.array([0, 1, 2, 2, 1, 1])  Because I think 'for loop' will consume lots of time. Is there any way to make fastest time calculation?

Answer: You can also use np.searchsorted as below: a = np.array([2, 5, 10, 13, 7, 9]) np.searchsorted([4, 9, 15], a) array([0, 1, 2, 2, 1, 1], dtype=int64)   labels = np.array([23, 45, 87]) labels[np.searchsorted([4, 9, 15], a)] array([23, 45, 87, 87, 45, 45])
Question: I have time series data in 4 channels and am trying to generate a sequence of length N using my model. I am determining N from the input data supplied to my sequence generation function: def generate_sequence(self, input_data): predicted_sequence = tf.convert_to_tensor(input_data, dtype=tf.float32) data_shape = predicted_sequence.shape for i in range(len(predicted_sequence)): model_input = tf.reshape(predicted_sequence, shape=data_shape) result = self.model(model_input) predicted_sequence = tf.concat([predicted_sequence[:, 1:, :], result], 0) return predicted_sequence  This causes the following error: ConcatOp : Dimension 1 in both shapes must be equal: shape[0] = [1,1439,4] vs. shape[1] = [1,1,4] [Op:ConcatV2] name: concat This seems to suggest that I am using the wrong method to generate my sequence (I naively wrote this function assuming that tensorflow tensors would behave like numpy arrays). In my loop I start with my input data: [[[a1, b1, c1, d1] [a2, b2, c2, d2] ... [aN, bN, cN, dN]]  and I generate a prediction using my model: [[aP1, bP1, cP1, dP1]]  My intention at this point is to remove the first entry in the input data, as it is the oldest row of data, and add the predicted data to the end: [[[a2, b2, c2, b2] [a3, b3, c3, d3] ... [aN, bN, cN, dN] [aP1, bP1, cP1, dP1]]]  From here the loop is run until the entire sequence contains predictions for the next N rows of data. Is there another tensorflow method that is better suited to this or am I missing something in the tf.concat method? Any help would be greatly appreciated.

Answer: Everything is good except the axis of concatenation. It should be axis=1. def generate_sequence(self, input_data): predicted_sequence = tf.convert_to_tensor(input_data, dtype=tf.float32) data_shape = predicted_sequence.shape for i in range(len(predicted_sequence)): model_input = tf.reshape(predicted_sequence, shape=data_shape) result = self.model(model_input) predicted_sequence = tf.concat([predicted_sequence[:, 1:, :], result], axis=1) return predicted_sequence  The rule of thumb is "all the tensors should possess the same shape in all the axes except the concatenating axis"
Question: I'm working with a deeply nested DataFrame (not good practice, I know), and I'd like to express something like "select field X for all structs in list Y". An example of the data structure: import polars as pl data = { "a": [ [{ "x": [1, 2, 3], "y": [4, 5, 6] }, { "x": [2, 3, 4], "y": [3, 4, 5] } ] ], } df = pl.DataFrame(data)  In this case, I'd like to select field "x" in both of the structs, and gather them into a df with two series, call them"x_1" and "x_2". In other words, the desired output is: ┌───────────┬───────────┐ │ x_1 ┆ x_2 │ │ --- ┆ --- │ │ list[i64] ┆ list[i64] │ ╞═══════════╪═══════════╡ │ [1, 2, 3] ┆ [2, 3, 4] │ └───────────┴───────────┘  I don't know the length of the list ahead of time, and I'd like to do this dynamically (i.e. without hard-coding the field names). I'm not sure whether this is possible using Polars expressions? Thanks in advance!

Answer: Update: Perhaps a simpler approach using .unstack() (df.select(pl.col("a").flatten().struct.field("x")) .unstack(1) )  shape: (1, 2) ┌───────────┬───────────┐ │ x_0 ┆ x_1 │ │ --- ┆ --- │ │ list[i64] ┆ list[i64] │ ╞═══════════╪═══════════╡ │ [1, 2, 3] ┆ [2, 3, 4] │ └───────────┴───────────┘   Original answer: df.select( pl.col("a").list.eval(pl.element().struct["x"]) .list.to_struct("max_width", lambda idx: f"x_{idx + 1}") ).unnest("a")  shape: (1, 2) ┌───────────┬───────────┐ │ x_1 ┆ x_2 │ │ --- ┆ --- │ │ list[i64] ┆ list[i64] │ ╞═══════════╪═══════════╡ │ [1, 2, 3] ┆ [2, 3, 4] │ └───────────┴───────────┘  Explanation  .list.eval() to loop through each list element, we extract each struct field.  df.select( pl.col("a").list.eval(pl.element().struct["x"]) ) # shape: (1, 1) # ┌────────────────────────┐ # │ a │ # │ --- │ # │ list[list[i64]] │ # ╞════════════════════════╡ # │ [[1, 2, 3], [2, 3, 4]] │ # └────────────────────────┘   .list.to_struct() to convert to a struct which will allow us to turn each inner list into its own column.  df.select( pl.col("a").list.eval(pl.element().struct["x"]) .list.to_struct("max_width", lambda idx: f"x_{idx + 1}") ) # shape: (1, 1) # ┌───────────────────────┐ # │ a │ # │ --- │ # │ struct[2] │ # ╞═══════════════════════╡ # │ {[1, 2, 3],[2, 3, 4]} │ # └───────────────────────┘   .unnest() the struct to create individual columns.
Question: I am trying to use Gensim, but running import gensim raises this error: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.10/dist-packages/gensim/__init__.py", line 11, in <module> from gensim import parsing, corpora, matutils, interfaces, models, similarities, utils # noqa:F401 File "/usr/local/lib/python3.10/dist-packages/gensim/corpora/__init__.py", line 6, in <module> from .indexedcorpus import IndexedCorpus # noqa:F401 must appear before the other classes File "/usr/local/lib/python3.10/dist-packages/gensim/corpora/indexedcorpus.py", line 14, in <module> from gensim import interfaces, utils File "/usr/local/lib/python3.10/dist-packages/gensim/interfaces.py", line 19, in <module> from gensim import utils, matutils File "/usr/local/lib/python3.10/dist-packages/gensim/matutils.py", line 20, in <module> from scipy.linalg import get_blas_funcs, triu ImportError: cannot import name 'triu' from 'scipy.linalg' (/usr/local/lib/python3.10/dist-packages/scipy/linalg/__init__.py)  Why is this happening and how can I fix it?

Answer: I found the issue.  The scipy.linalg functions tri, triu & tril are deprecated and will be removed in SciPy 1.13. — SciPy 1.11.0 Release Notes § Deprecated features  So, I installed SciPy v1.10.1 instead of the latest version and it was working well. pip install scipy==1.10.1
Question: In my code, I need to distinguish a list of records from a list of lists of records. The existing code does it like so: if isinstance(input_var, list): if len(input_var) > 0: if all(isinstance(item) for item in input_var): return list_of_lists_processing(input_var) elif not any(instance(item, list) for item in input_var): return list_of_data_processing(input_var) else: raise ValueError(f"Unexpected input_var value {input_var}") else: return list() else: raise ValueError(f"Unexpected input_var value {input_var}")  However, this seems ugly. I want to use Python 3.10's pattern matching to simplify the code. I came up with this version: match input_var: case [list(), *_]: return list_of_lists_processing(input_var) case list(): # also process empty list case return list_of_data_processing(input_var) case _: ValueError(f"Unexpected value {input_var=}")  But there is a flaw here: case [*list(), *_] only checks the first element of input_var, not all of them. In practice, this is enough for my purposes, but I want to ask anyway: is there a clean way to match only a list where every element is a list? I tried case [*list()]:, but this causes a SyntaxError. case list(list()): is syntactically correct, but doesn't work as expected (for example, it matches ["a"] - what is going on here?)

Answer: You can match the set of item types inside your list. class Constants: set_of_list = {list} match set(type(elem) for elem in input_var): case Constants.set_of_list: return list_of_lists_processing(input_var) case types if list in types: raise ValueError(f"Unexpected input_var value {input_var}") case _: return list_of_data_processing(input_var)  Python3.10 does not support matching values inside a set so you still have to check if list is one of the types. The Constants class is used to trigger a value pattern. Raymond Hettinger made a great talk to explain this and other concepts related to pattern matching.
Question: After updating Visual Studio Code to version 1.88.0, I opened one of my Python projects and noticed that there are double parentheses in my virtual environment: ((env) ). I'm using the Python extension v2024.4.0  Previously, in the same and all other projects, I had only one pair of parentheses like (env). I have checked, but I didn't find any information about it. I have read that (venv1) (venv2) indicates a double virtual environment, but I don't know if this is the case. I have tried deleting the env (I have the requirement.txt) or closing/reopening VSCode, but the problem persists. Any suggestions on how to fix it? I have checked the files: .bashrc, .zshrc, .bash_profile, but everything seems fine. Also, by starting a new project from scratch, the problem persists.

Answer: It's an issue with the Python extension v2024.4.0. Reverting to the previous version, v2024.2.1, fixed this issue for me.
Question: I was trying to make plots using matplotlib into GIFs for further analysis, when during the analysis I noticed that the output of the analysis consisted of less images than expected. I created and saved 3956 plots with axes turned off (this would make my analysis simpler) then proceeded to create GIFs in the easiest way I found, using PIL, I opened the images to a list, then sorted the list into 2 further lists of 1978 images, then used im.save with save_all=True and append_images=im[1:]. The code ran without an issue and the GIFs opened normally. It was during the further analysis I noticed something was up and I confirmed it later using GIMP that the two output GIFs had 1798 and 1784 images only, instead of the 1978 I used to create them. The opening of the images shouldn't be the problem as the opened image lists both have lengths of 1978, the problem has to happen with the code: imS[0].save( "filename.gif", save_all=True, append_images=imS[1:], duration=250, loop=0)  I tried using multiple image formats, tried changing the duration, tried changing the "interlace" and "optimize" options in im.save(), deleting and reinstalling the PIL module, none of them changed the result. I thought that there might be an issue with consecutive images being empty (Each image is supposed to show data in a unit time and there are intervals with no data so that's where the empty images come from) and some compression is deleting the multiple empty images but this clearly isn't the case after eyeballing the GIFs. That's where I'm stuck

Answer: I do not have enough reputation to make this a comment, so I respond without solving the issue completely, sorry for that. I was running into the same issue until now. Does your list of frames contain duplicates or very similar frames? In this git issue it is outlined that it is intended behaviour from pillow to remove these duplicates. Here they explicitly state:  Removing duplicate consecutive frames is intended to be a feature, reducing file size without affecting the visual output.  Currently, I am also stuck with this and cannot find a solution as the workarounds from the git issue do not work anymore. My workaround is to create a list of pngs in python and then compose them using ImageMagick.
Question: platform:windows server 2019 python:3.12.2 scipy:1.13.0 When I upgraded scipy from 1.12 to 1.13 there was No module named scipy.special._cdflib.This doesn't happen when I use 1.12.0. Traceback (most recent call last): File "src\predict.py", line 14, in <module> from src.utils.calc_utils import * File "PyInstaller\loader\pyimod02_importers.py", line 419, in exec_module File "src\utils\calc_utils.py", line 1, in <module> from scipy.interpolate import interp1d File "PyInstaller\loader\pyimod02_importers.py", line 419, in exec_module File "scipy\interpolate\__init__.py", line 167, in <module> File "PyInstaller\loader\pyimod02_importers.py", line 419, in exec_module File "scipy\interpolate\_interpolate.py", line 10, in <module> File "PyInstaller\loader\pyimod02_importers.py", line 419, in exec_module File "scipy\special\__init__.py", line 777, in <module> File "scipy\\special\\_ufuncs.pyx", line 1, in init scipy.special._ufuncs ModuleNotFoundError: No module named 'scipy.special._cdflib'  How to solve this problem? Why does this problem occur?

Answer: Appenrently this is a known issue in pyinstaller, look at which version you have. In the changelog it states  Update scipy.special._ufuncs hook for compatibility with SciPy 1.13.0 (add scipy.special._cdflib to hidden imports). (#8394)  So using version 6.6.0 of pyinstaller might work
Question: I am fairly new to Matplotlib and appreciate your help with my question: I am looking to generate a figure that each label has 2 colors. For example, a label named 'first_color\nsecond_color', first and second color are different. If I use label.set_color(colors[0]), the whole color of label will be changed. If I use label.set_color(colors[i % 2]), the color of neighboring label will be different. I just want different color in single internal label. labels = ['1first_color\nsecond_color', '2first_color\nsecond_color', '3first_color\nsecond_color', '4first_color\nsecond_color', '5first_color\nsecond_color'] colors = [sns.color_palette('tab10')[0], sns.color_palette('tab10')[1]] plt.plot(range(len(labels)), [0, 1, 2, 3, 4]) plt.xticks(range(len(labels)), labels) for i, label in enumerate(plt.gca().get_xticklabels()): label.set_color(colors[0]) #label.set_color(colors[i % 2])   label.set_color(colors[0])  label.set_color(colors[i % 2]) I am sure there is support for such a feature in Matplotlib. I did look through the docs/forums but could not find much help. Any suggestions will be much appreciated. I want to know how to set multiple colors at single label.

Answer: If the tick labels need a different color on different lines, you can explicit place text at the tick positions. With an x-axis transform, the x-position can be given in "data coordinates" (0 for the first label, 1 for the second, etc.) and the y-position in "axes coordinates" (0 at the bottom, 1 at the top of the "ax", negative values for positions below the "ax"). You may need to change the y-positions a bit, depending on the tick lengths and fonts used. import matplotlib.pyplot as plt import seaborn as sns labels = ['1first_color\nsecond_color', '2first_color\nsecond_color', '3first_color\nsecond_color', '4first_color\nsecond_color', '5first_color\nsecond_color'] colors = sns.color_palette('tab10')[:2] plt.plot(range(len(labels)), [0, 1, 2, 3, 4]) plt.xticks(range(len(labels)), []) # set tick positions without labels ax = plt.gca() # get the current subplot for i, label in enumerate(labels): ax.text(i, -0.03, label.split('\n')[0], color=colors[0], transform=ax.get_xaxis_transform(), ha='center', va='top') ax.text(i, -0.08, label.split('\n')[1], color=colors[1], transform=ax.get_xaxis_transform(), ha='center', va='top') plt.tight_layout() plt.show()
Question: I have a custom directory structure which is not the traditional "src" or "flat" layouts setuptools expects. This is a sample of the directory tree: my_git_repo/ ├── Dataset/ │ ├── __init__.py │ ├── data/ │ │ └── some_csv_file.csv │ ├── some_ds1_script.py │ └── some_ds2_script.py └── Model/ ├── __init__.py ├── utils/ │ ├── __init__.py │ ├── some_utils1_script.py │ └── some_utils2_script.py └── some_model/ ├── __init__.py ├── some_model_script.py └── trained_models/ ├── __init__.py └── model_weights.pkl  Lets say that my package name inside the pyproject.toml is "my_ai_package" and the current packages configuration is: [tools.setuptools.packages.find] include = ["*"] namespaces = false  After building the package, what I currently get is inside my site-packages directory I have the Dataset & Model directories What I want is a main directory called "my_ai_package" and inside it the Dataset & Model directories, I want to be able to do "from my_ai_package import Dataset.some_ds1_script" I can't re-structure my directory tree to match src/flat layouts, I need some custom configuration in pyptoject.toml Thanks!

Answer: I ended up re-structuring my project in a "src" layout where "src" is replaced by my package name
Question: I am using datacompy to compare all columns from two dataframe. My goal is to extract the column(s) name with unmatched values. In the below example, I used inventory_id as a join column to compare df1 and df2. One column shows unmatched value, which is 'indinv_vari_ware_uid'. This is a simple example, in real work situation, it's common to see more than one column with unmatched values. Is there a way to programmatically extract these unmatched column name from the result? The end goal is to print these column names in a text file or in the log instead of having users to read the compare report (there will be hundreds of them in each production run). import datacompy compare = datacompy.Compare(df1, df2, join_columns=['inventory_id'], df1_name='df1', df2_name='df2') print(compare.report())  

Answer: You can use compare.column_stats for this: a list with dictionaries that contain the relevant information per column.  Sample setup:  import pandas as pd import datacompy data = {'id': [1, 2], 'col1': [1, 2]} df1 = pd.DataFrame(data) data2 = {'id': [1, 2], 'col1': ['A', 'B']} df2 = pd.DataFrame(data2) compare = datacompy.Compare(df1, df2, join_columns=['id'])   Print:  print(compare.report()) # ... Columns with Unequal Values or Types ------------------------------------ Column df1 dtype df2 dtype # Unequal Max Diff # Null Diff 0 col1 int64 object 2 0.0 0 Sample Rows with Unequal Values ------------------------------- id col1 (df1) col1 (df2) 0 2 2 B 1 1 1 A   Access column_stats:  compare.column_stats [{'column': 'id', 'match_column': '', 'match_cnt': 2, 'unequal_cnt': 0, 'dtype1': 'int64', 'dtype2': 'int64', 'all_match': True, 'max_diff': 0.0, 'null_diff': 0}, {'column': 'col1', 'match_column': 'col1_match', 'match_cnt': 0, 'unequal_cnt': 2, 'dtype1': 'int64', 'dtype2': 'object', 'all_match': False, 'max_diff': 0.0, 'null_diff': 0}]   Use a list comprehension to get all column names where unequal_cnt != 0:  unmatched_columns = [stat['column'] for stat in compare.column_stats if stat['unequal_cnt'] != 0] unmatched_columns # ['col1']  It might also be convenient to create a df with pd.DataFrame, and filter as desired: column_stats = pd.DataFrame(compare.column_stats) column_stats column match_column match_cnt unequal_cnt dtype1 dtype2 all_match \ 0 id 2 0 int64 int64 True 1 col1 col1_match 0 2 int64 object False max_diff null_diff 0 0.0 0 1 0.0 0 # e.g. column_stats[column_stats['unequal_cnt'].ne(0)]
Question: This is a revisit to the question Add columns to pandas dataframe containing max of each row, AND corresponding column name where a solution was provided using the now deprecated method ix. How can you do the same thing using iloc or loc instead? I've tried both, but I'm getting:  IndexError: boolean index did not match indexed array along dimension 0; dimension is 3 but corresponding boolean dimension is 5  Here's a sample DataFrame:  a b c maxval 0 1 0 0 1 1 0 0 0 0 2 0 1 0 1 3 1 0 0 1 4 3 1 0 3  And here's the desired output:  a b c maxval maxcol 0 1 0 0 1 a 1 0 0 0 0 a,b,c 2 0 1 0 1 b 3 1 0 0 1 a 4 3 1 0 3 a 

Answer: Here ix is used to select the columns up to c, you can do the same with loc: df['maxcol'] = (df.loc[:, :'c'].eq(df['maxval'], axis=0) .apply(lambda x: ','.join(df.columns[:3][x==x.max()]),axis=1) )  Or, since [:3] is used later with iloc: df['maxcol'] = (df.iloc[:, :3].eq(df['maxval'], axis=0) .apply(lambda x: ','.join(df.columns[:3][x==x.max()]),axis=1) )  A variant with a dot product: tmp = df.loc[:, :'c'] df['maxcol'] = (tmp.eq(df['maxval'], axis=0) @ (tmp.columns+',')).str[:-1]  Or melt+groupby.agg: df['maxcol'] = (df .melt('maxval', ignore_index=False) .query('maxval == value') .groupby(level=0)['variable'].agg(','.join) )  Output:  a b c maxval maxcol 0 1 0 0 1 a 1 0 0 0 0 a,b,c 2 0 1 0 1 b 3 1 0 0 1 a 4 3 1 0 3 a
Question: I'm stuck with a cum_sum problem where I only want tot cumulatively sum unique values over a column. Here's an example of what I want to achieve: ┌─────┬─────┬─────┐ │ a ┆ b ┆ d │ │ --- ┆ --- ┆ --- │ │ i64 ┆ i64 ┆ i64 │ ╞═════╪═════╪═════╡ │ 1 ┆ 1 ┆ 1 │ │ 1 ┆ 2 ┆ 2 │ │ 1 ┆ 3 ┆ 3 │ │ 1 ┆ 1 ┆ 1 │ │ 2 ┆ 1 ┆ 4 │ │ 2 ┆ 2 ┆ 4 │ │ 2 ┆ 2 ┆ 5 │ │ 2 ┆ 2 ┆ 5 │ └─────┴─────┴─────┘  a and b are my input columns where a is the group and b is the unique id within he group. I want to generate d which is a unique id across all groups. I'm not able to figure out a way to do this. Here's what I've managed - I can get the max per group by using over but then I don't know how to do the cumsum to get the unique ids. import polars as pl df = pl.DataFrame({'a': [1,1,1,1,2,2,2,2], 'b': [1,2,3,1,1,2,2,2]}) df.with_columns(c = pl.max('b').over('a')).with_columns(pl.cum_sum("c").over("c").alias("d")) Out[60]: shape: (8, 4) ┌─────┬─────┬─────┬─────┐ │ a ┆ b ┆ c ┆ d │ │ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ i64 ┆ i64 ┆ i64 │ ╞═════╪═════╪═════╪═════╡ │ 1 ┆ 1 ┆ 3 ┆ 3 │ │ 1 ┆ 2 ┆ 3 ┆ 6 │ │ 1 ┆ 3 ┆ 3 ┆ 9 │ │ 1 ┆ 1 ┆ 3 ┆ 12 │ │ 2 ┆ 1 ┆ 2 ┆ 2 │ │ 2 ┆ 2 ┆ 2 ┆ 4 │ │ 2 ┆ 2 ┆ 2 ┆ 6 │ │ 2 ┆ 2 ┆ 2 ┆ 8 │ └─────┴─────┴─────┴─────┘  I'm sure this must be pretty simple but I can't figure this out - It seems like I need a cumsum the unique values of c and then add to b to get the unique id but maybe I need some sort of conditional sum of c only if it's values changes? It seems like I should be doing something similar to this answer (https://stackoverflow.com/a/74985568/1506763) but I'm stuck.

Answer: You might be looking for pl.Expr.rank with method="dense". df.with_columns( pl.struct("a", "b").rank("dense").alias("id") )  shape: (8, 3) ┌─────┬─────┬─────┐ │ a ┆ b ┆ id │ │ --- ┆ --- ┆ --- │ │ i64 ┆ i64 ┆ u32 │ ╞═════╪═════╪═════╡ │ 1 ┆ 1 ┆ 1 │ │ 1 ┆ 2 ┆ 2 │ │ 1 ┆ 3 ┆ 3 │ │ 1 ┆ 1 ┆ 1 │ │ 2 ┆ 1 ┆ 4 │ │ 2 ┆ 2 ┆ 5 │ │ 2 ┆ 2 ┆ 5 │ │ 2 ┆ 2 ┆ 5 │ └─────┴─────┴─────┘
Question: I have two DataFrames A =    0 1 2     0 0.5 0   0.1 0 0.2   0.2 0 0    and B =    0     1.0   1.0   NaN    I need to multiply each row of A by B element-wise, but I need the computation done so that the resulting dataframe shows a NaN only if the original element of A is 0. If I do A * B.transpose()  I get    0 1 2     0 0.5 NaN   0.1 0 NaN   0.2 0 NaN    but I need it to be    0 1 2     0 0.5 NaN   0.1 0 0.2   0.2 0 NaN    import pandas as pd A = pd.DataFrame([[0, 0.5, 0], [0.1, 0, 0.2], [0.2, 0, 0]]) B = pd.DataFrame([1, 1, np.NaN]) 

Answer: IIUC you can try: out = A * B.T.values out[out.isna() & ~A.eq(0)] = A print(out)  Prints:  0 1 2 0 0.0 0.5 NaN 1 0.1 0.0 0.2 2 0.2 0.0 NaN
Question: I have a dataframe with two-level column names as: ID Value A B ---------------- 1 6 2 5 3 4 4 3 5 2 6 1  I want to change the column head with: column_mapping = { ('ID', 'A') : 'ID:A', ('Value', 'B'): 'Value:B' }  I tried rename: df.rename(columns=column_mapping, inplace=True)  which does not work. Any idea how?

Answer: Try: df.columns = df.columns.map(":".join) print(df)  Prints:  ID:A Value:B 0 1.0 6.0 1 2.0 5.0 2 3.0 4.0 3 4.0 3.0 4 5.0 2.0 5 6.0 1.0