Python 如何使用数据帧对多个字符串进行分组和筛选?

Python 如何使用数据帧对多个字符串进行分组和筛选?,python,pandas,string,apply,Python,Pandas,String,Apply,我是一名编码初学者,我已经尝试了几天寻找答案,但我没有成功我想做的事,所以提前道歉,如果它很容易,或者如果它已经存在于某个地方。。。 假设我有一个带有列的df1:series_id和discosure_name,我想通过用series_id和lung_ref_seg列替换df1来获得df2。对于df1中的同一系列id,我可以有几个名称(图左)。在df2(图右)中,我希望一个序列id只有一个病变名称。如果一个序列id有一个对应的病变名称,该名称有“lung”和“PredCorr”,我将把它作为lu

我是一名编码初学者,我已经尝试了几天寻找答案,但我没有成功我想做的事,所以提前道歉,如果它很容易,或者如果它已经存在于某个地方。。。 假设我有一个带有列的df1:series_id和discosure_name,我想通过用series_id和lung_ref_seg列替换df1来获得df2。对于df1中的同一系列id,我可以有几个名称(图左)。在df2(图右)中,我希望一个序列id只有一个病变名称。如果一个序列id有一个对应的病变名称,该名称有“lung”和“PredCorr”,我将把它作为lung\u ref\u seg的首选。如果病变名称没有“lung”和“PredCorr”,但有“lung”和“From”,我将把它作为lung\u ref\u seg的第二选择。如果病变名称没有两个第一选择中的任何一个,我会选择病变名称,它有'Pred'和'lung'作为lung\u ref\u seg的第三个选择。(病变名称可以有Nan值,我想将它们保存在lung_ref_seg中)。我已经尝试了很多东西(groupby、filter、str.contains、isin、lambda row…),所以我只想放一个我认为接近解决方案的代码:

lesion_name = test['lesion_name']
series_id = test['series_id']

def LungSegRef(lesion_name):
    for rows in series_id:
        if 'PredCorr' in lesion_name and 'lung' in lesion_name:
            return lesion_name
        elif 'PredCorr' not in lesion_name and 'From' in lesion_name and 'lung' in lesion_name:
            return lesion_name
        elif 'PredCorr' not in lesion_name and 'From' not in lesion_name and 'Pred' in lesion_name and 'lung' in lesion_name:
            return lesion_name
    return ''


# Apply the function RefLesionName 
test['lung_ref_seg'] = test['lesion_name'].apply(LungSegRef)
这样我就没有错误了,我在整个列lung\u ref\u seg中只有Nan值,并且仍然有多个相同的series\u id值。所以我想我们可以在某个地方使用groupby(“series_id”),也许我在函数中的参数是错误的。非常感谢你的帮助

这些行不是重复的。我发现了一些应该有效的方法,但我正在努力区分包含Pred和PredCorr的值,因为当我使用contains时,它不会在仅包含Pred的行和包含PredCorr的行之间产生差异。对于这段代码,我不能使用startswith()和endswith()。我试图用正则表达式找到答案,但目前我没有找到任何东西来区分只包含Pred和lung的行与包含PredCorr和lung的行

 def select_row2(row2):
    if row2.lesion_name.str.contains("Pred" and "lung" and "Corr" and "From",na=True).any():
        return row2[row2.lesion_name.str.contains("Corr" and "lung",na=True)]
       
    elif row2.lesion_name.str.contains("Pred" and "lung" and "Corr",na=True).any():
        return row2[row2.lesion_name.str.contains("Corr" and "lung",na=True)]
    
    elif row2.lesion_name.str.contains("lung" and "Corr" and "From",na=True).any():
        return row2[row2.lesion_name.str.contains("Corr" and "lung",na=True)]
    
    elif row2.lesion_name.str.contains("Pred" and "lung" and "From",na=True).any():
        return row2[row2.lesion_name.str.contains("From" and "lung",na=True)]
    
    elif row2.lesion_name.str.contains("Pred" and "lung",na=True).any():
        return row2[row2.lesion_name.str.contains("Pred" and "lung",na=True)]
    
    elif row2.lesion_name.str.contains("lung" and "Corr",na=True).any():
        return row2[row2.lesion_name.str.contains("lung" and "Corr",na=True)]
    
    elif row2.lesion_name.str.contains("lung" and "From",na=True).any():
        return row2[row2.lesion_name.str.contains("lung" and "From",na=True)]
    
    else:
        return None 

test = test.groupby("series_id").apply(select_row2).reset_index(drop=True) 

我认为您可以将此过程分为两步:

  • 首先,筛选出您想要保留的数据(似乎包含特定字符串的特定值就是您想要的-但是我对您在这里的帖子有点困惑)
  • 其次,从series_id列中删除重复项。这将导致每个值都只有一个值
  • 正如您所提到的,使用df.filter函数进行过滤(尽管您也可以使用
    df['lung\u ref\u seg']=df[df['lung\u ref\u seg'].str.contains('STRING TO KEEP'))


    删除重复项可以通过
    df来完成。删除重复项(子集=['series\u id'])

    我找到了一个现在似乎有效的答案

    # We remove all lesion_name that contains string "tum" to work on creating the column lung_ref_seg (and we keep nan values)
    
    test = test[~test.lesion_name.str.contains("tum",na=False)]
    
    # Define the function to pick one lesion_name for one series_id prioritizing PredCorr first then From and then Pred for the last choice
    
    def LungRefLesionName(row):
        if row.lesion_name.str.contains("(Pred)\w+" or "From" or "(Pred)\b", na=True).any():
            return row[row.lesion_name.str.contains("(Pred)\w+", na=True)]
            
        elif row.lesion_name.str.contains("From" or "(Pred)\b", na=True).any(): 
            return row[row.lesion_name.str.contains("From", na=True)] 
        
        elif row.lesion_name.str.contains("(Pred)\b" and "lung", na=True).any():
            return row[row.lesion_name.str.contains("(Pred)\b" and "lung", na=True)]
    
    # Apply the function
    test = test.groupby("series_id").apply(LungRefLesionName).reset_index(drop=True)
    
    
    # Drop columns that we don't need anymore : segmentation_id, lesion_id, series_id and study_id
    
    test = test.drop(['segmentation_id', 'lesion_id', 'series_id', 'study_id'], axis = 1)
    
    # Renaming column lesion_name by lung_ref_lesion_name
    
    test = test.rename(columns={"lesion_name": "lung_ref_lesion_name"})
    
    

    稍后我将对包含“tum”的名称进行修改,因此我想我必须更改一些内容,但现在这段代码适用于使用“lung”操纵字符串!

    非常感谢您的回答!不幸的是,这些行没有重复…我编辑了这篇文章,也许您可以了解更多,并帮助我有所不同区分包含lung和Pred的行以及包含lung和PredCorr的行(更多详细信息请参阅帖子)。再次感谢!