【问题标题】:Recursively group rows and columns of python DataFrame递归分组python DataFrame的行和列
【发布时间】:2021-06-14 11:14:13
【问题描述】:

我有一个 DataFrame 表示行项目与索引从 0 到 1 的列项目的相似性。 我想对更相似的项目进行分组并通过删除分组的项目行和列来创建一个新的数据框,然后添加一个行和列都用包含 2 个合并项目的元组索引,然后再次执行该过程,直到我已经分组所有的项目。 现在我想出了这个代码:

我首先从一个名为 gupt_seiff 的元组字典中创建 2 个数据帧,一个将保持不变,而另一个将被修改:

gupt_seiff_df = pd.DataFrame(index = workshops, columns = workshops)
for el in gupt_seiff:
    gupt_seiff_df.at[el[0], el[1]] = gupt_seiff[el]
gupt_seiff_df2 = pd.DataFrame(index = workshops, columns = workshops)
for row in gupt_seiff_df.index:
    for col in gupt_seiff_df.columns:
        gupt_seiff_df2.at[row, col] = gupt_seiff_df.at[row, col]

这是我打印 gupt_seiff_df 和 gupt_seiff_df2 的结果:

              clav acciaio tornio montaggio 3 montaggio 1 tav controllo lavatrice montaggio 2 montaggio 4
clav acciaio           1.0    1.0         0.0         0.0           1.0       1.0         0.0         0.0
tornio                 1.0    1.0         0.0         0.0           1.0       1.0         0.0         0.0
montaggio 3            0.0    0.0         1.0         0.0           0.0       0.0    0.059823    0.075803
montaggio 1            0.0    0.0         0.0         1.0           0.0       0.0    0.019964         0.0
tav controllo          1.0    1.0         0.0         0.0           1.0       1.0         0.0         0.0
lavatrice              1.0    1.0         0.0         0.0           1.0       1.0         0.0         0.0
montaggio 2            0.0    0.0    0.059823    0.019964           0.0       0.0         1.0    0.884966
montaggio 4            0.0    0.0    0.075803         0.0           0.0       0.0    0.884966         1.0
              clav acciaio tornio montaggio 3 montaggio 1 tav controllo lavatrice montaggio 2 montaggio 4
clav acciaio           1.0    1.0         0.0         0.0           1.0       1.0         0.0         0.0
tornio                 1.0    1.0         0.0         0.0           1.0       1.0         0.0         0.0
montaggio 3            0.0    0.0         1.0         0.0           0.0       0.0    0.059823    0.075803
montaggio 1            0.0    0.0         0.0         1.0           0.0       0.0    0.019964         0.0
tav controllo          1.0    1.0         0.0         0.0           1.0       1.0         0.0         0.0
lavatrice              1.0    1.0         0.0         0.0           1.0       1.0         0.0         0.0
montaggio 2            0.0    0.0    0.059823    0.019964           0.0       0.0         1.0    0.884966
montaggio 4            0.0    0.0    0.075803         0.0           0.0       0.0    0.884966         1.0

现在我想找到具有最大相似性的项目,或者数据框中索引最高的 (row, col) 对。我设法做到了,唯一值得一提的是,对角线中的值被排除在外,因为它们代表了一个项目和它本身的相似性,当然是 1,如果在对角线之外有一对与相同的相似性,先合并哪一对并不重要,所以我只是合并第一个。

现在我有一个包含几个具有最大相似性的项目的元组,这将是我的第一个集群。例如:

print(cluster)
('tav controllo', 'lavatrice')

所以在这种情况下,我要做的是删除名为 tav controllo 和 lavatrice 的行和列,并添加索引为 ('tav controllo', 'lavatrice') 的行和列。 预期的结果是这样的:

gupt_seiff_df2 = gupt_seiff_df2.drop(cluster[0], axis=0)
gupt_seiff_df2 = gupt_seiff_df2.drop(cluster[0], axis=1)
gupt_seiff_df2 = gupt_seiff_df2.drop(cluster[1], axis=0)
gupt_seiff_df2 = gupt_seiff_df2.drop(cluster[1], axis=1)
new_row_col = pd.Series({cluster[0] + cluster[1]: 1}, name=cluster[0] + cluster[1])
gupt_seiff_df2 = gupt_seiff_df2.append(new_row_col)
                       clav acciaio montaggio 2 tornio montaggio 3 montaggio 4 montaggio 1  tav controllolavatrice
clav acciaio                    1.0         0.0    1.0         0.0         0.0         0.0                     NaN
montaggio 2                     0.0         1.0    0.0    0.059823    0.884966    0.019964                     NaN
tornio                          1.0         0.0    1.0         0.0         0.0         0.0                     NaN
montaggio 3                     0.0    0.059823    0.0         1.0    0.075803         0.0                     NaN
montaggio 4                     0.0    0.884966    0.0    0.075803         1.0         0.0                     NaN
montaggio 1                     0.0    0.019964    0.0         0.0         0.0         1.0                     NaN
tav controllolavatrice          NaN         NaN    NaN         NaN         NaN         NaN                     1.0

但这里的问题是它只有在我连接项目的字符串名称时才有效。 我想要的是保留集群元组的 2 个不同元素,因为现在我必须计算集群与其他项目的相似性值,例如 ('tav controllo', 'lavatrice') 与'clav acciaio' 将是新项目元组中项目的平均值:

gupt_seiff_df2.at[('tav controllo', 'lavatrice'), 'clav acciaio'] = (gupt_seiff_df.at['tav controllo', 'clav acciaio'] + gupt_seiff_df.at['lavatrice', 'clav acciaio'])/2

以此类推来填充所有的 NaN 值。 也可能发生我必须计算 2 个元组之间的平均值,因此它将是第一个元组和第二个元组之间所有组合的相似度值的平均值。例如,如果我有一个包含 3 个项目的元组和一个包含 2 个项目的元组,我将有 3x2 = 6 个相似度值,然后我将计算平均值。

我正在尝试使用此代码保留元组索引:

gupt_seiff_df2 = gupt_seiff_df2.drop(cluster[0], axis=0)
gupt_seiff_df2 = gupt_seiff_df2.drop(cluster[0], axis=1)
gupt_seiff_df2 = gupt_seiff_df2.drop(cluster[1], axis=0)
gupt_seiff_df2 = gupt_seiff_df2.drop(cluster[1], axis=1)
new_row_col = pd.Series({cluster: 1}, name=cluster)
gupt_seiff_df2 = gupt_seiff_df2.append(new_row_col)

但我收到以下错误:

Traceback (most recent call last):
  File "C:\Users\damia\PycharmProjects\logistic_management_tool\Main_es.py", line 9, in <module>
    plant = Plant(loader_)
  File "C:\Users\damia\PycharmProjects\logistic_management_tool\plant.py", line 168, in __init__
    gupt_seiff_df2 = gupt_seiff_df2.append(new_row_col)
  File "C:\Users\damia\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\frame.py", line 7960, in append
    other.reindex(combined_columns, copy=False)
  File "C:\Users\damia\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\series.py", line 4345, in reindex
    return super().reindex(index=index, **kwargs)
  File "C:\Users\damia\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\generic.py", line 4811, in reindex
    return self._reindex_axes(
  File "C:\Users\damia\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\generic.py", line 4827, in _reindex_axes
    new_index, indexer = ax.reindex(
  File "C:\Users\damia\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\indexes\multi.py", line 2492, in reindex
    target = MultiIndex.from_tuples(target)
  File "C:\Users\damia\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\indexes\multi.py", line 175, in new_meth
    return meth(self_or_cls, *args, **kwargs)
  File "C:\Users\damia\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\indexes\multi.py", line 531, in from_tuples
    arrays = list(lib.tuples_to_object_array(tuples).T)
  File "pandas\_libs\lib.pyx", line 2537, in pandas._libs.lib.tuples_to_object_array
TypeError: Expected tuple, got str

最后,我想用新的 gupt_seiff_df2 重复这个过程。最终结果必须是一个 1x1 DataFrame,索引是所有项目的集群:

cluster_all_items = (clav acciaio, tornio, montaggio 3, montaggio 1, tav controllo, lavatrice, montaggio 2, montaggio 4)

                    (cluster_all_items)

(cluster_all_items)         1

【问题讨论】:

    标签: python pandas recursion tuples multi-index


    【解决方案1】:

    我想你还在寻找解决方案...

    我认为.append 的问题源于对索引的误解。元组最有可能导致 MultiIndex 然后与数据框的标签发生冲突(我已经查看了相应的 Pandas 实现,但最终迷路了)。这是一个不错的解决方法:

    带样框

    df = pd.DataFrame({'A': [1, 2], 'B': [2, 1]}, index=['A', 'B'])
    
       A  B
    A  1  2
    B  2  1
    

    这个

    cluster = ('A', 'B')
    df = df.append(pd.Series({cluster: 1}, name=cluster))
    

    由于同样的原因失败了,但是这个

    cluster = ('A', 'B')
    df = pd.concat([df, pd.Series({cluster: 1})])
    df.columns = df.columns.to_list()[:-1] + [cluster]
    

    结果(print(df)

              A    B  (A, B)
    A       1.0  2.0     NaN
    B       2.0  1.0     NaN
    (A, B)  NaN  NaN     1.0
    

    这似乎有你想要的结构。

    也许有帮助。

    【讨论】:

    • 感谢您的回答,但我现在正在尝试使用 scikit 的 AgglomerativeClustering 解决这个问题!
    猜你喜欢
    • 2018-06-29
    • 1970-01-01
    • 2019-01-03
    • 2013-03-21
    • 1970-01-01
    • 2017-02-21
    • 1970-01-01
    • 2018-05-29
    • 2020-08-15
    相关资源
    最近更新 更多