将 collections.Counters 的组合频率从数据帧多索引转换为字符串

Posted

技术标签:

【中文标题】将 collections.Counters 的组合频率从数据帧多索引转换为字符串【英文标题】:Converting collections.Counters of combinations frequency from dataframe multi-index into string 【发布时间】:2021-07-09 16:12:54 【问题描述】:

想请教一些关于如何正确执行此操作的建议。我是 python 新手。

最初我想找出多索引组合的计数器/频率。我尝试了几种方法,例如循环、itertuples、iterrows 等,我意识到最快和最少开销是使用 collections.Counter

但是,它返回多索引索引组合的元组列表作为计数器字典键。元组的键使得后续处理变得困难。

因此,我正在研究如何将它们变成带有分隔符的字符串,以便之后的处理更易于管理。

例如下面这个多索引:

# testing
def testing():
    testing_df = pd.read_csv("data/testing.csv", float_precision="high")
    testing_df = testing_df.set_index(["class", "table", "seat"]).sort_index()
    print("\n1: \n" + str(testing_df.to_string()))

    print("\n2 test: \n" + str(testing_df.index))
    occurrences = collections.Counter(testing_df.index)

    print("\n3: \n" + str(occurrences))

输出:

1: 
                    random_no
class   table seat           
Emerald 1     0         55.00
Ruby    0     0         33.67
              0         24.01
              1         87.00
Topaz   0     0         67.00

2 test: 
MultiIndex([('Emerald', 1, 0),
            (   'Ruby', 0, 0),
            (   'Ruby', 0, 0),
            (   'Ruby', 0, 1),
            (  'Topaz', 0, 0)],
           names=['class', 'table', 'seat'])

3: 
Counter(('Ruby', 0, 0): 2, ('Emerald', 1, 0): 1, ('Ruby', 0, 1): 1, ('Topaz', 0, 0): 1)

从3)我们可以看出,它返回不同数据类型的元组中的组合作为dict键,处理起来很困难。

我尝试将它分开或使其成为字符串,以便处理它更容易。

尝试以下错误:

x = "|".join(testing_df.index)
print(x)

 x = "|".join(testing_df.index)
TypeError: sequence item 0: expected str instance, tuple found

以下有错误

x = "|".join(testing_df.index[0])
print(x)

 x = "|".join(testing_df.index[0])
 TypeError: sequence item 1: expected str instance, numpy.int64 found

基本上,它是:

    我在计算 collections.Counter 或之前将组合变成字符串 将其制成 collections.Counter 后,其中所有众多键都是元组并将这些键转换为字符串

请问我该如何正确执行此操作?

非常感谢!

【问题讨论】:

【参考方案1】:

我可以为2.提供一个解决方案,将键元组转换为字符串:

from collections import Counter
# recreate your problem
occurrences = Counter([('Ruby', 0, 0),
    ('Ruby', 0, 0),
    ('Emerald', 1, 0),
    ('Ruby', 0, 1),
    ('Topaz', 0, 0)])

# convert tuple keys to string keys
new_occurrences = '|'.join(str(index) for index in key) : value for key,value in occurrences.items()
print(new_occurrences)
'Ruby|0|0': 2, 'Emerald|1|0': 1, 'Ruby|0|1': 1, 'Topaz|0|0': 1

Counterdict 的子类,因此您可以使用 dict-comprehensions 和 .items() 等花哨的东西同时循环键和值。

根据您打算如何进一步处理数据,将计数器的结果转换为pandas DataFrame 可能更有用。仅仅是因为pandas 提供了更多更简单的处理功能。

方法如下:

import pandas as pd
df = pd.DataFrame('class': [k[0] for k in occurrences.keys()],
    'table': [k[1] for k in occurrences.keys()],
    'seat': [k[2] for k in occurrences.keys()],
    'counts': [v for _,v in occurrences.items()])
df.head()
     class  table  seat  counts
0     Ruby      0     0       2
1  Emerald      1     0       1
2     Ruby      0     1       1
3    Topaz      0     0       1

【讨论】:

以上是关于将 collections.Counters 的组合频率从数据帧多索引转换为字符串的主要内容,如果未能解决你的问题,请参考以下文章

将结果减少到累积的组中

将用户添加到 django 中的组

将 DataFrame 拆分为来自多列的组字典

将标签分配给不同的组分配方案

vbscript 将UserFormControls跨页/标签链接到各自的组

Drupal Group 模块,以编程方式将用户添加到具有特定角色的组