当索引级别具有相同值时,替换 pandas 数据帧多索引第二级上的奇异值

发布于 2025-01-13 18:01:14 字数 1264 浏览 6 评论 0原文

我有一个数据框,它有两个级别的多重索引。给出第二级的以下示例:

d = {
"col1": [1, 2, 3, 4],
"col2": [1, 2, 3, 4],
"col3": [1, 2, 3, 4],
"col4": [1, 2, 3, 4],
"col5": [1, 2, 3, 4],
}
df = pd.DataFrame(data=d)
df.columns = pd.MultiIndex.from_product([df.columns, ["identical"]])

如何更改奇异值以使索引的第二级看起来像这样?

['example', 'identical', 'identical', 'identical', 'identical']

我尝试这样做:

        updated_columns = list(df.columns.get_level_values(1))

        updated_columns[0] = 'example'

        df.columns.set_levels(
            updated_columns, level=1, inplace=True, verify_integrity=False
        )

在这种情况下我的更改被忽略。

我也尝试过此主题的答案: pandas MultiIndex with重复值一级

        df.columns = pd.MultiIndex.from_tuples(
            df.columns.set_levels(updated_columns, 1, verify_integrity=False).values
        )

这也被忽略了。

我还考虑过使用 rename() 方法。不幸的是,它仅在提供重命名的列的值时才有效。鉴于存在相同的值,这是行不通的。

对于非多重索引,有这种方法:

df.columns.values[0] = 'example'

但根据我收集的信息,它不适用于多重索引。

我添加了 verify_integrity=False 因为该方法不允许我设置相同的值。

任何帮助将不胜感激。

I have a dataframe that has a multiindex with two levels. Given the following example for the second level:

d = {
"col1": [1, 2, 3, 4],
"col2": [1, 2, 3, 4],
"col3": [1, 2, 3, 4],
"col4": [1, 2, 3, 4],
"col5": [1, 2, 3, 4],
}
df = pd.DataFrame(data=d)
df.columns = pd.MultiIndex.from_product([df.columns, ["identical"]])

How do I change a singular value so that the second level of the index looks like this?

['example', 'identical', 'identical', 'identical', 'identical']

I have tried to do it this way:

        updated_columns = list(df.columns.get_level_values(1))

        updated_columns[0] = 'example'

        df.columns.set_levels(
            updated_columns, level=1, inplace=True, verify_integrity=False
        )

My change is ignored in this case.

I have also tried the answer from this topic: pandas MultiIndex with duplicate values in one level

        df.columns = pd.MultiIndex.from_tuples(
            df.columns.set_levels(updated_columns, 1, verify_integrity=False).values
        )

Which was also ignored.

I have also considered using the rename() method. Unfortunately it only works if the value of the column that is renamed is provided. Given that there are identical values, this will not work.

For non-multiindexes there is this method:

df.columns.values[0] = 'example'

But from what I have gathered, it will not work for a multi index.

I have added verify_integrity=False because the method would not otherwise allow me to set identical values.

Any help would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

神魇的王 2025-01-20 18:01:14

一种方法是获取组成 MultiIndex 的元组并直接修改它们:

    tuples = df.columns.tolist()
    tuples[0] = (tuples[0][0], 'example')

    df.columns = pd.MultiIndex.from_tuples(tuples)

输出:

>>> df
     col1      col2      col3      col4      col5
  example identical identical identical identical
0       1         1         1         1         1
1       2         2         2         2         2
2       3         3         3         3         3
3       4         4         4         4         4

MultiIndexes 有点奇怪。它们存储为级别列表(其中包含唯一的标签值)和代码(标签的索引)。例如,当前 MultiIndex 的级别和代码如下所示:

>>> df.columns.levels
FrozenList([['col1', 'col2', 'col3', 'col4', 'col5'], ['identical']])

>>> df.columns.codes
FrozenList([[0, 1, 2, 3, 4], [0, 0, 0, 0, 0]])

如您所见,其中只有一个 'indentical' 字符串。它的重复是由代码定义的。

因此,如果您想通过操作级别和代码将第二级的第一个标签设置为 example,您可以像这样进行操作:

vals = df.columns.levels[1].tolist()
vals.append('example')

df.columns = df.columns.set_levels(vals, level=1)
df.columns = df.columns.set_codes([1, 0, 0, 0, 0], level=1) # 1 = 'example', 2 = 'identical'

这是一个函数,您可以使用它来设置MultiIndex 的特定级别:

def set_level_of_df(df, level_index, labels):
    new_df = df.copy()
    
    unique, inverse = np.unique(labels, return_inverse=True)
    new_df.columns = new_df.columns.set_levels(unique, level=level_index)
    new_df.columns = new_df.columns.set_codes(inverse, level=level_index)
    return new_df

用法:

>>> df
     col1      col2      col3      col4      col5
  example identical identical identical identical
0       1         1         1         1         1
1       2         2         2         2         2
2       3         3         3         3         3
3       4         4         4         4         4

>>> df = set_level_of_df(df, level_index=0, labels=['aaa', 'abc', 'xyz', '0123', '-----'])
>>> df
      aaa       abc       xyz      0123     -----
  example identical identical identical identical
0       1         1         1         1         1
1       2         2         2         2         2
2       3         3         3         3         3
3       4         4         4         4         4

这是另一个函数(使用前一个函数),您可以使用它来设置 MultiIndex 的特定级别的特定标签(这是您的问题):

def set_label_of_label_of_df(df, level_index, label_index, label):
    new_df = df.copy()
    
    labels = df.columns.get_level_values(level=level_index).tolist()
    labels[label_index] = label
    return set_level_of_df(df, level_index, labels)

用法:

>>> df
     col1      col2      col3      col4      col5
  example identical identical identical identical
0       1         1         1         1         1
1       2         2         2         2         2
2       3         3         3         3         3
3       4         4         4         4         4

>>> df = set_label_of_label_of_df(df, level_index=1, label_index=3, label='THIS_IS_A_TEST_VALUE')
>>> df
     col1      col2      col3                 col4      col5
  example identical identical THIS_IS_A_TEST_VALUE identical
0       1         1         1                    1         1
1       2         2         2                    2         2
2       3         3         3                    3         3
3       4         4         4                    4         4

One way would be to get the tuples that make up the MultiIndex and modify them directly:

    tuples = df.columns.tolist()
    tuples[0] = (tuples[0][0], 'example')

    df.columns = pd.MultiIndex.from_tuples(tuples)

Output:

>>> df
     col1      col2      col3      col4      col5
  example identical identical identical identical
0       1         1         1         1         1
1       2         2         2         2         2
2       3         3         3         3         3
3       4         4         4         4         4

MultiIndexes are a bit weird. They're stored as a list of levels (which contain unique label values), and codes (which are the indexes of the labels). For example, the levels and codes for your current MultiIndex look like this:

>>> df.columns.levels
FrozenList([['col1', 'col2', 'col3', 'col4', 'col5'], ['identical']])

>>> df.columns.codes
FrozenList([[0, 1, 2, 3, 4], [0, 0, 0, 0, 0]])

As you can see, there's only one 'indentical' string in there. The repetitions of it are defined by the codes.

So if you wanted to set the first label of the second level to example by manipulating the levels and codes, you might go about it like this:

vals = df.columns.levels[1].tolist()
vals.append('example')

df.columns = df.columns.set_levels(vals, level=1)
df.columns = df.columns.set_codes([1, 0, 0, 0, 0], level=1) # 1 = 'example', 2 = 'identical'

Here's a function that you can use to set all the labels of a particular level of a MultiIndex:

def set_level_of_df(df, level_index, labels):
    new_df = df.copy()
    
    unique, inverse = np.unique(labels, return_inverse=True)
    new_df.columns = new_df.columns.set_levels(unique, level=level_index)
    new_df.columns = new_df.columns.set_codes(inverse, level=level_index)
    return new_df

Usage:

>>> df
     col1      col2      col3      col4      col5
  example identical identical identical identical
0       1         1         1         1         1
1       2         2         2         2         2
2       3         3         3         3         3
3       4         4         4         4         4

>>> df = set_level_of_df(df, level_index=0, labels=['aaa', 'abc', 'xyz', '0123', '-----'])
>>> df
      aaa       abc       xyz      0123     -----
  example identical identical identical identical
0       1         1         1         1         1
1       2         2         2         2         2
2       3         3         3         3         3
3       4         4         4         4         4

Here's another function (which uses the previous one) that you can use to set a particular label of a particular level of a MultiIndex (which is your question):

def set_label_of_label_of_df(df, level_index, label_index, label):
    new_df = df.copy()
    
    labels = df.columns.get_level_values(level=level_index).tolist()
    labels[label_index] = label
    return set_level_of_df(df, level_index, labels)

Usage:

>>> df
     col1      col2      col3      col4      col5
  example identical identical identical identical
0       1         1         1         1         1
1       2         2         2         2         2
2       3         3         3         3         3
3       4         4         4         4         4

>>> df = set_label_of_label_of_df(df, level_index=1, label_index=3, label='THIS_IS_A_TEST_VALUE')
>>> df
     col1      col2      col3                 col4      col5
  example identical identical THIS_IS_A_TEST_VALUE identical
0       1         1         1                    1         1
1       2         2         2                    2         2
2       3         3         3                    3         3
3       4         4         4                    4         4
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文