从列表中删除列中的重复信息

2024-09-28 16:23:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要清理一个数据帧,删除重复的信息。例如:

    name                                       strength
770 Vitamin B12 Tab 500mcg                     500 mcg
771 Vitamin B12 Tab 5mcg                       5 mcg
772 Vitamin B12 Tablets 250mcg                 250 mcg
773 Vitamin B12-folic Acid                     None
774 Vitamin B6 & B12 With Folic Acid           None
775 Vitamin Deficiency Injectable System - B12 None
776 Vitamine 110 Liq                           None
777 Vitamine B-12 Tab 100mcg                   100 mcg
778 Vitamine B12 25 Mcg - Tablet               25 mcg
779 Vitamine B12 250mcg                        250 mcg

从第一name列中,我需要删除strength中的信息,即:

    name                                       strength
770 Vitamin B12 Tab                            500 mcg
771 Vitamin B12 Tab                            5 mcg
772 Vitamin B12 Tablets                        250 mcg
773 Vitamin B12-folic Acid                     None
774 Vitamin B6 & B12 With Folic Acid           None
775 Vitamin Deficiency Injectable System - B12 None
776 Vitamine 110 Liq                           None
777 Vitamine B-12 Tab                          100 mcg
778 Vitamine B12 - Tablet                      25 mcg
779 Vitamine B12                               250 mcg

注意,name中的强度表示可能与strength列中的强度表示不完全对应,直到空格(500 mcg对500 mcg)

我的简单解决方案是循环所有可能的strength组合,如果name列中有匹配项,则替换为空字符:

new_df = []

for i in df:
    for j in df.strength.dropna().drop_duplicates().tolist():
        for k in i.split():
            if j == k: 
                new_df.append((i, i.replace(j, '')))

print(new_df)

它确实有效,但是,我有大量的数据,这是最不符合pythonic和最不高效的实现方式。你知道吗

有什么建议吗?你知道吗


Tags: 数据nameinnone信息dfnewfor
3条回答

我可能无法与所有可能的力量组合相匹配。由于两个列的项目似乎包含大致相同的字符,所以使用strength列来模糊搜索name列就足够了。你知道吗

你可以搜索不区分大小写的有和没有空格,你可能会得到大多数项目完成。你知道吗

不区分大小写的搜索可以通过python中的正则表达式完成:

import re

# case insensitive without whitespace
if re.search('5 mcg'.replace(" ",""), 'Vitamin B12 Tab 5mcg', re.IGNORECASE):
    # is True
elif re.search('25 mcg', 'Vitamine B12 25 Mcg - Tablet', re.IGNORECASE):
    # is True

当然,用变量替换文本。你知道吗

编辑:可能有一种更有效的方法来处理正则表达式,所以如果有人更精通正则表达式,我很乐意学习。你知道吗

new_df=[]  
df= df[df[strength]!=None]# Firstly select the column with Non None values.     
df['name']= df[name].str.split()   
for i in df[name]:  
   for j in df[strength]:    
        if j in i:   
            i.remove(j)   
        else:   
             pass   
   new_df.append(' '.join(i))

这可能是一个更好的方法。首先,我们正在减少数据和for循环之一,这将使代码的复杂性由o(n3)变为o(n2)

使用re包删除不需要的冗余字符串,并使用apply函数删除pandasDataFrame中的行。你知道吗

在下面的代码中,您可以看到一个可能的解决方案:

import pandas as pd
import re

def removeReduntantData(row):
    if row["strength"] is not None:
        string = row["strength"].replace(" ", "\s?")
        return re.sub(re.compile(string+"\s?", re.IGNORECASE), "", row["name"]).strip()
    else:
        return row["name"]

df = pd.DataFrame({"name":["Vitamin B12 Tab 500mcg","Vitamin B12 Tab 5mcg","Vitamin B12 Tablets 250mcg","Vitamin B12-folic Acid","Vitamin B6 & B12 With Folic Acid","Vitamin Deficiency Injectable System - B12","Vitamine 110 Liq","Vitamine B-12 Tab 100mcg","Vitamine B12 25 Mcg - Tablet","Vitamine B12 250mcg"],\
"strength":["500 mcg","5 mcg","250 mcg",None,None,None,None,"100 mcg","25 mcg","250 mcg"]})

df["name"] = df.apply(removeReduntantData, axis=1)

然后输出DataFrame

>>> df
                                         name strength
0                             Vitamin B12 Tab  500 mcg
1                             Vitamin B12 Tab    5 mcg
2                         Vitamin B12 Tablets  250 mcg
3                      Vitamin B12-folic Acid     None
4            Vitamin B6 & B12 With Folic Acid     None
5  Vitamin Deficiency Injectable System - B12     None
6                            Vitamine 110 Liq     None
7                           Vitamine B-12 Tab  100 mcg
8                       Vitamine B12 - Tablet   25 mcg
9                                Vitamine B12  250 mcg

这样,您就可以使用strength列在name列中查找冗余字符串并将其删除,同时考虑到冗余字符串之间可能没有空格。你知道吗

相关问题 更多 >