我正在尝试使用NLP技术来预测医生记录时患者的心理状态。我有两个类,后缀(multilabel(和mental_status(binary、Lucid或Delirium(。我正在尝试从符合以下规范的精简列表中构建训练和测试集:
- 共享的唯一后缀列表
- 对于每个后缀的每组,Lucid和Delirium至少有一行
我将用样本权重纠正任何不平衡(我只是试图预测mental_status,但我也需要在后缀上平衡数据(。我只需要后缀和mental_statuses的完整笛卡尔乘积中的每个组合至少有一行。
例如,在下面的数据集中,只有DWM通信后缀才能进入列车测试拆分。
suffix mental_status
DWN Communication Lucid
DWN Communication Delirium
DWN Communication Lucid
DWN Communication Delirium
DWN Communication Lucid
DWN Psychiatry Lucid
DWN Psychiatry Delirium
DWN Psychiatry Delirium
DWN Cardio stuff Lucid
DWN Cardio stuff Delirium
DWN Blood ..... Lucid
DWN Blood ..... Lucid
DWN Blood ..... Lucid
对于上面的火车例子,我想要的输出是
DWN Communication Lucid
DWN Communication Delirium
DWN Communication Lucid
并测试
DWN Communication Lucid
DWN Communication Delirium
我试过
df.groupby(['suffix','mental_status']).filter(lambda x: len(x) > 1)
但它不能确保每个后缀都有一个Delirium和Lucid。
作为另一个例子,
suf ms
11 blood delirium
15 blood delirium
0 blood lucid
1 blood lucid
5 blood lucid
6 blood lucid
10 blood lucid
16 blood lucid
3 psych delirium
19 psych delirium
4 psych lucid
8 psych lucid
9 psych lucid
13 psych lucid
14 psych lucid
18 psych lucid
7 stool delirium
2 stool lucid
12 stool lucid
17 stool lucid
将被拆分为
suf ms
11 blood delirium
0 blood lucid
1 blood lucid
5 blood lucid
6 blood lucid
3 psych delirium
4 psych lucid
8 psych lucid
9 psych lucid
13 psych lucid
和
suf ms
15 blood delirium
10 blood lucid
16 blood lucid
19 psych delirium
14 psych lucid
18 psych lucid
编辑:
我想我找到了一个解决方案:
from sklearn.model_selection import train_test_split
def custom_split(df, test_size):
f = lambda ms: (
df[df.mental_status==ms]
.groupby('suffix')
.filter(lambda x:len(x)>=1/min(test_size,1-test_size))
.suffix
)
delirium = f('Delirium')
lucid = f('Lucid')
valid_suffixes = set(delirium).intersection(lucid)
df = df[df.suffix.isin(valid_suffixes)]
df_train, df_test = train_test_split(df,test_size,random_state=9,
stratify=df.mental_status+df.suffix)
return df_train, df_test
使用索引和duplicated(keep=False)
怎么样?
test = df[~df.duplicated(keep=False)]
output = df.drop_duplicates()
output = output[~output.index.isin(test.index)]
如果只执行df.drop_duplicates(inplace=True)
,它能工作吗?看起来这就是它的全部内容,因为您只需要基于两列组合的唯一值。
使用掩码过滤器:
mask = df["DWN" in df['suffix']]
df = df[mask]
df.dropna(inplace=True)
使用Groupby
data="""index,suf,ms
11,blood,delirium
15,blood,delirium
0,blood,lucid
1,blood,lucid
5,blood,lucid
6,blood,lucid
10,blood,lucid
16,blood,lucid
3,psych,delirium
19,psych,delirium
4,psych,lucid
8,psych,lucid
9,psych,lucid
13,psych,lucid
14,psych,lucid
18,psych,lucid
7,stool,delirium
2,stool,lucid
12,stool,lucid
17,stool,lucid"""
df = pd.read_csv(io.StringIO(data), sep=',')
#print(df)
lst=[]
grouped=df.groupby(['suf','ms'])
for group in grouped.groups:
lst.append(group)
print(lst)
输出:
[('blood', 'delirium'), ('blood', 'lucid'), ('psych', 'delirium'), ('psych', 'lucid'), ('stool', 'delirium'), ('stool', 'lucid')]
您现在可以使用元组作为过滤器