【问题标题】:Drawing a random sub-sample from a df proportionally to categories从 df 中按类别抽取随机子样本
【发布时间】:2021-02-27 12:34:33
【问题描述】:

我有一个这样的数据框

names = ["Patient 1", "Patient 2", "Patient 3", "Patient 4", "Patient 5", "Patient 6", "Patient 7"]
categories = ["Internal medicine, Gastroenterology", "Internal medicine, General Med, Endocrinology", "Pediatrics, Medical genetics, Laboratory medicine", "Internal medicine", "Endocrinology", "Pediatrics", "General Med, Laboratory medicine"]

zippedList =  list(zip(names, categories))
df = pd.DataFrame(zippedList, columns=['names', 'categories'])

屈服:

print(df)
names                                         categories
0  Patient 1                Internal medicine, Gastroenterology
1  Patient 2      Internal medicine, General Med, Endocrinology
2  Patient 3  Pediatrics, Medical genetics, Laboratory medicine
3  Patient 4                                  Internal medicine
4  Patient 5                                      Endocrinology
5  Patient 6                                         Pediatrics
6  Patient 7                   General Med, Laboratory medicine

(实际数据框有 >1000 行)

并计算类别产量:

print(df['categories'].str.split(", ").explode().value_counts())

Internal medicine      3
General Med            2
Endocrinology          2
Laboratory medicine    2
Pediatrics             2
Gastroenterology       1
Medical genetics       1

我想抽取n 行的随机子样本,以便按比例表示每个中间类别。例如13 个类别中的 3 个(~23%)是“内科”。因此,约 23% 的子样本应具有此类别。如果每个患者有 1 个类别,这不会太难,但不幸的是他们可以有多个(例如,患者 3 甚至有 3 个类别)。我该怎么做?

【问题讨论】:

  • 我建议您使用train_test_split 并传递stratify 参数。然后,您可以定义测试集的大小并在其余代码中使用它。见这里:stackoverflow.com/a/36998108/5763165.
  • stratify 可以工作,但它不能解决一列中的多标签问题...
  • 所以这取决于您是否想为多标签选项提供更多权重。您可以将它们视为一个单独的类别并在它们之间进行分层。其他选项可能是复制列表中每个类别的“患者”数据,然后分层,然后随机删除最终 df 中的重复项。
  • 要真正保持您所追求的比率(例如,上面引用的 3/13),您需要将不同的组合视为一个单独的类别(例如,您可以将列表视为一个唯一的字符串),然后在它们之间分层。

标签: python dataframe subsampling


【解决方案1】:

您的患者有很多类别这一事实不会影响二次抽样过程。当您从 nrows 中取出 n 行(即 len(df) )时,子采样将保持类别权重,+/- 一个类别在您的随机子集中更具代表性的概率 - 随着 n 变高,它会收敛到 0-

通常,

n = 2000
df2 = df.sample(n).copy(deep = True)
print(df2['categories'].str.split(", ").explode().value_counts())

应该按照你想要的方式工作。

我还了解到您有大约 1000 个类别。不要忘记在使用前对其进行预处理,因为其中一些可能会在您的二次采样拟合后消失。

【讨论】:

  • 将每个类别抽样到正确的大小可以保证保持比例,而不是仅仅希望收敛到真实的比例。尤其是如果您有非常罕见的类别,您可能会因为这种方法而失去它们。
猜你喜欢
  • 1970-01-01
  • 2020-04-24
  • 1970-01-01
  • 2016-04-22
  • 2013-08-17
  • 2017-05-11
  • 2019-12-28
  • 1970-01-01
  • 2018-01-15
相关资源
最近更新 更多