【问题标题】:Sum rows and columns of DataFrame with MultiIndex使用 MultiIndex 对 DataFrame 的行和列求和
【发布时间】:2021-07-14 15:56:29
【问题描述】:

我正在尝试编写一个函数,该函数将 2D 方形 DataFrame 和索引列表作为输入,并返回一个包含行索引和列索引总和的新 DataFrame。 这里有一个例子的代码:

import pandas as pd
import numpy as np

def cluster_sum(matrix, cluster):

    matrix[tuple(cluster)] = matrix[cluster].sum(axis=1)
    matrix = matrix.drop(cluster, axis=1)
    matrix = matrix.append(pd.Series(matrix.loc[cluster, :].sum(axis=0), name=tuple(cluster)))
    matrix = matrix.drop(cluster, axis=0)

    return matrix

idx = ['a', 'b', 'c']
sample_df = pd.DataFrame(np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]]), index=idx, columns=idx)
print(sample_df)

当前数据帧:

   a  b  c
a  0  1  1
b  1  0  1
c  1  1  0

我定义了一个集群并应用 cluster_sum:

cluster = ['a', 'b']

new_df = cluster_sum(sample_df, cluster)
print(new_df)

结果如我所愿:

        c  (a, b)
c       0       2
(a, b)  2       2

现在问题来了:如果我尝试选择新行(a,b): print(new_df.loc[('a', 'b'), :]) 它给了我以下错误:

Traceback (most recent call last):
  File "C:\Users\damia\PycharmProjects\logistic-tool\try2.py", line 23, in <module>
    print(new_df.loc[('a', 'b'), :])
  File "C:\Users\damia\PycharmProjects\print\venv\lib\site-packages\pandas\core\indexing.py", line 925, in __getitem__
    return self._getitem_tuple(key)
  File "C:\Users\damia\PycharmProjects\print\venv\lib\site-packages\pandas\core\indexing.py", line 1109, in _getitem_tuple
    return self._getitem_tuple_same_dim(tup)
  File "C:\Users\damia\PycharmProjects\print\venv\lib\site-packages\pandas\core\indexing.py", line 806, in _getitem_tuple_same_dim
    retval = getattr(retval, self.name)._getitem_axis(key, axis=i)
  File "C:\Users\damia\PycharmProjects\print\venv\lib\site-packages\pandas\core\indexing.py", line 1153, in _getitem_axis
    return self._getitem_iterable(key, axis=axis)
  File "C:\Users\damia\PycharmProjects\print\venv\lib\site-packages\pandas\core\indexing.py", line 1093, in _getitem_iterable
    keyarr, indexer = self._get_listlike_indexer(key, axis)
  File "C:\Users\damia\PycharmProjects\print\venv\lib\site-packages\pandas\core\indexing.py", line 1314, in _get_listlike_indexer
    self._validate_read_indexer(keyarr, indexer, axis)
  File "C:\Users\damia\PycharmProjects\print\venv\lib\site-packages\pandas\core\indexing.py", line 1374, in _validate_read_indexer
    raise KeyError(f"None of [{key}] are in the [{axis_name}]")
KeyError: "None of [Index(['a', 'b'], dtype='object')] are in the [index]"

我做了一些研究,我确定问题出在元组形式的索引上。我认为熊猫希望我在新行中使用 MultiIndex,并且最好在列中也使用 MultiIndex,但我不熟悉 MultiIndex。我尝试创建一个具有 MultiIndex 名称的 Series,然后将其添加到 DataFrame,但我认为创建 MultiIndex Series 是不可能的,所以我在这里寻求建议。

编辑:将索引放在方括号内,如下所示:new_df.loc[[('a', 'b')], :] 对我来说不是一个好的解决方案,因为我需要检查索引是否是元组,这不是一个有效的解决方案。像这样的:

for i in new_df.index:
    if type(i) is tuple:
        print(new_df.loc[[i], :])
    else:
        print(new_df.loc[i, :])

它会起作用,但必须有一个更有效的解决方案......

【问题讨论】:

  • 索引列表 (cluster) 的长度可以超过 2 项吗?您在问题中提到MultiIndex;如果集群大小可以超过 2,或者如果您打算多次运行它,那么您当前的方法或使用 MultiIndex 的任何替代实现都不能是免费的 if..else (因为这样各种行将具有任意深度索引) .对上下文进行更多澄清可能会有所帮助。

标签: python pandas dataframe tuples multi-index


【解决方案1】:

要选择元组索引,请将("a", "b") 放入[ ]

print(new_df.loc[[("a", "b")], :])

打印:

        c  (a, b)
(a, b)  2       2

【讨论】:

  • 感谢您的回答,但关键是要做到这一点,我需要知道某个索引是否是元组,如果我想遍历数据帧索引,这是一个问题.如果我想对 n 个索引使用 for 循环(矩阵可以是任意长度,这只是一个示例),我需要添加一个 if 语句来检查索引的类型是否为元组。一定有更有效的方法!
猜你喜欢
  • 2022-06-11
  • 2019-10-28
  • 2018-06-24
  • 1970-01-01
  • 2015-09-09
  • 2018-08-22
  • 2017-10-16
  • 1970-01-01
相关资源
最近更新 更多