pandas 从一组组中获取唯一组

bogh5gae  于 2023-03-16  发布在  其他
关注(0)|答案(2)|浏览(116)

我试图从Excel文件中找到一个列(这里是字母列)中的唯一组。数据看起来像这样:
| 身份证|字母|
| - ------|- ------|
| 1个|A、B、D、E、F|
| 三个|B、C类|
| 第二章|B|
| 七十五|T型|
| 五十四|K、M|
| 九|D、B|
| 二十三|B、D、A|
| 三十四|X、Y、Z|
| 六十七|X、Y|
| 十二|E、D|
| 十五|G级|
| 十个|G级|
| 十一|F级|
一个组的任何元素都不应该出现在另一个组的元素中。根据上表,输出文件应该如下所示:
| 身份证|字母|
| - ------|- ------|
| 七十五|T型|
| 五十四|K、M|
因为这些组的任何元素都没有与其他组共享。
我尝试的代码:

df: pd.DataFrame = pd.DataFrame([
["A, B, D, E, F"], ["B, C"], ["B"], ["T"],  ["K, M"], ["D, B"], ["B, D, A"], ["X, Y, Z"], ["X, Y"],
["E, D"], ["G"], ["G"]], columns=["letters"])
if __name__ == "__main__":
sub_ids=[]
for i in range(len(df)):
    temp_sub_ids = []
    curr_letters_i = df.iloc[i]["letters"].replace(" ", "").split(",")
    for j in range(len(df)):
        if i == j:
            continue
        curr_letters_j = df.iloc[j]["letters"].replace(" ", "").split(",")
        if not any([letter in curr_letters_i for letter in curr_letters_j]):
       
            temp_sub_ids.append(f"{df.iloc[j]['id']}")
       
    sub_ids.append(",".join(temp_sub_ids))
df["sub-ids"] = sub_ids
print(df)

有了这个代码,它给每个身份证作为子身份证,没有任何共享的信件。但我想搜索所有信件组,如果没有任何共享信件与其他组,那么它将是唯一的。

zzlelutf

zzlelutf1#

算法:

  • 基于在正则表达式分隔符上拆分letter列来附加辅助列letter_,所述正则表达式分隔符具有作为值/元素列表的每个组
  • 分解/展开letter_,以便将每个值放置在单独的行中
  • 将每个letter_值Map到其频率(其出现次数)
  • 筛选器letter(初始组),仅包含出现一次的项目(最大计数为1
df = df.assign(letter_=df['letter'].str.split(r'\s*,\s*')).explode('letter_')
df['letter_'] = df['letter_'].map(df['letter_'].value_counts())
df = df.groupby('letter').filter(lambda x: x['letter_'].max() == 1)\
    .drop_duplicates().drop('letter_', axis=1).reset_index(drop=True)
print(df)
id letter
0  75      T
1  54   K, M
ubbxdtey

ubbxdtey2#

要从your previous question继续my answer,我只需要向 Dataframe 添加一个简单的唯一性测试作为新列:

import pandas as pd

df: pd.DataFrame = pd.DataFrame([
    [1, "A, B, D, E, F"], [3, "B, C"], [2, "B"], [75, "T"], [54, "K, M"],
    [9, "D, B"], [23, "B, D, A"], [34, "X, Y, Z"], [67, "X, Y"],
    [12, "E, D"], [15, "G"], [10, "G"], [11, "F"]
], columns=["id", "letters"])

threshold = 0.5

if __name__ == "__main__":
    sub_ids = []
    sub_scores = []
    sub_unique = []
    for i in range(len(df)):
        temp_sub_ids = []
        temp_sub_scores = []
        temp_unique = True
        curr_letters_i = df.iloc[i]["letters"].replace(" ", "").split(",")
        for j in range(len(df)):
            if i == j:
                continue
            curr_letters_j = df.iloc[j]["letters"].replace(" ", "").split(",")
            if any([letter in curr_letters_i for letter in curr_letters_j]):
                temp_unique = False
            if not all([letter in curr_letters_i for letter in curr_letters_j]):
                continue
            if len(curr_letters_j)/len(curr_letters_i) >= threshold:
                temp_sub_ids.append(f"{df.iloc[j]['id']}")
                temp_sub_scores.append(f"{len(curr_letters_j)/len(curr_letters_i):.2f}")
        sub_ids.append(",".join(temp_sub_ids))
        sub_scores.append(temp_sub_scores)
        sub_unique.append(temp_unique)
    df["sub-ids"] = sub_ids
    df["sub-scores"] = sub_scores
    df["unicity"] = sub_unique
    print(df)

这就产生了

id        letters sub-ids sub-scores  unicity
0    1  A, B, D, E, F      23     [0.60]    False
1    3           B, C       2     [0.50]    False
2    2              B                 []    False
3   75              T                 []     True
4   54           K, M                 []     True
5    9           D, B       2     [0.50]    False
6   23        B, D, A       9     [0.67]    False
7   34        X, Y, Z      67     [0.67]    False
8   67           X, Y                 []    False
9   12           E, D                 []    False
10  15              G      10     [1.00]    False
11  10              G      15     [1.00]    False
12  11              F                 []    False

可以过滤(print(df.loc[df["unicity"] == True])为

id letters sub-ids sub-scores  unicity
3  75       T                 []     True
4  54    K, M                 []     True

相关问题