如果至少一个单词与dataframe列中的其他单词重叠,则对行进行分组

时间:2016-06-24 21:14:21

标签: python pandas dataframe

我有一个数据框如下

       words    group_id
0  set([a, c, b, d])   1
1        set([a, b])   2
2  set([h, e, g, f])   3

我需要将行分组为一,即使集合中的一个单词(单词)与另一行中的单词重叠,也要更新group_id。

       words    group_id
0  set([a, c, b, d])   1
1        set([a, b])   1
2  set([h, e, g, f])   3

我试过这种方式

word_frequency = Counter()

for val in df['words'].values:
    word_frequency.update(val)

to_return = np.array(word_frequency.most_common())
count = 1

df['group_id'] = np.zeros(len(df)) * np.nan
for val in to_return:
    df['group_id'] = df[['group_id','words']].apply(lambda x: count if (val in x) else np.NAN)
    count += 1

我该怎么做?

2 个答案:

答案 0 :(得分:1)

这可行,但效率非常低,因为它生成一组唯一的分组,然后为数据帧中的每个条目搜索一组唯一的分组。看到更有效的方法可以很好看。

def unique_grouper(series_of_entry_sets):
    set_of_groups = [series_of_entry_sets[0]]
    for potential_set in series_of_entry_sets:
        for i,accepted_set in enumerate(set_of_groups, start = 1):
            if accepted_set & potential_set:
                break
            else:
                set_of_groups.append(potential_set)
                break
    return set_of_groups

def group_identifier(current_set,set_of_groups):
    for i,unique_group in enumerate(set_of_groups):
        if current_set & unique_group:
            return i
    return None

df = pd.DataFrame({"Names":[set(["a", "c", "b", "d"]),set(["a", "b"]),set(["h", "e", "g", "f"]),set(["z"])]})
result =unique_grouper(df.Names)
df["group id"] = df.Names.apply(lambda x:group_identifier(x,result))

输出:

          Names  group id
0  {a, c, b, d}         0
1        {a, b}         0
2  {h, e, g, f}         1
3           {z}         2

答案 1 :(得分:0)

这是一个非常低效且被黑客攻击的解决方案,但仍有效:

import pandas as pd

df = pd.DataFrame({"Names":[set(["a", "c", "b", "d"]),set(["a", "b"]),set(["h", "e", "g", "f"]),set(["z"])]})

groups={}
idx=0
data=[]
for row in df.itertuples():
    values = row.Names
    groups[idx] = values
    for i in range(len(groups)):
        if len(values.intersection(groups[i])) > 0:
            not_found = False
            data.append(i)
            if len(groups[i]) - len(groups[idx]) > 0:
                groups[i] = values      #Replace with the larger set
            if idx>0:
                groups.pop(idx, None)
                idx-=1
        else:
            not_found = True
            break
        break
    if not_found:
        data.append(idx)
    idx+=1

df['group id'] = data

结果:

          Names  group id
0  {c, d, a, b}         0
1        {a, b}         0
2  {e, h, f, g}         1
3           {z}         2

您仍然应该使用apply方法,而不是遍历数据框中的每一行。