这是一个机器学习程序的需求。
我正在处理一个数据集,该数据集包含一个csv文件,csv文件中包含一个id,用于指向另一个目录中的.tif
图像,以及一个标签,1或0。csv文件中有220,025行。我已经将这个csv文件加载为pandas数据框。目前在数据框中,有220,025行,其中标签为0的行有130,908行,标签为1的行有89,117行。
标签为0的行比标签为1的行多出41,791行。我想随机删除这些多余的标签为1的行。之后,我希望将样本量从178,234减少到仅50,000,每个标签各有25,000个id。
另一种方法可能是随机删除105,908行标签为1的行和64,117行标签为0的行。
如何使用pandas来实现这一点?
我已经查看了使用.groupby
然后使用.sample
的方法,但这会在这两个标签中删除相同数量的行,而我只想删除一个标签中的行。
csv文件的样本:
id,labelf38a6374c348f90b587e046aac6079959adf3835,0c18f2d887b7ae4f6742ee445113fa1aef383ed77,1755db6279dae599ebb4d39a9123cce439965282d,0bc3f0c64fb968ff4a8bd33af6971ecae77c75e08,0068aba587a4950175d04c680d38943fd488d6a9d,0acfe80838488fae3c89bd21ade75be5c34e66be7,0a24ce148f6ffa7ef8eefb4efb12ebffe8dd700da,17f6ccae485af121e0b6ee733022e226ee6b0c65f,1559e55a64c9ba828f700e948f6886f4cea919261,08eaaa7a400aa79d36c2440a4aa101cc14256cda4,0
回答:
个人建议将这项任务分解为以下几个步骤:
由于0的数量多于1,我们首先要确保每个标签的数量相等。这里,我使用您粘贴的样本数据作为df
- 统计标签为1的数量(因为这是较小的值)
ones_subset = df.loc[df["label"] == 1, :]number_of_1s = len(ones_subset)print(number_of_1s)3
- 仅对标签为0的行进行抽样,使其数量与
number_of_1s
匹配
zeros_subset = df.loc[df["label"] == 0, :]sampled_zeros = zeros_subset.sample(number_of_1s)print(sampled_zeros)
- 将这两个部分(来自
ones_subset
的所有1和我们匹配的sampled_zeros
)拼接在一起,形成一个干净的数据框,其中1和0的标签数量相等
clean_df = pd.concat([ones_subset, sampled_zeros], ignore_index=True)print(clean_df) id label0 c18f2d887b7ae4f6742ee445113fa1aef383ed77 11 a24ce148f6ffa7ef8eefb4efb12ebffe8dd700da 12 7f6ccae485af121e0b6ee733022e226ee6b0c65f 13 559e55a64c9ba828f700e948f6886f4cea919261 04 f38a6374c348f90b587e046aac6079959adf3835 05 068aba587a4950175d04c680d38943fd488d6a9d 0
现在我们有了一个清理后的数据集,可以进行最后一步:
- 使用您提到的
groupby(...).sample(...)
方法进一步对这个数据集进行降采样。从一个包含每个标签各3个(三个1和三个0)的数据集,降采样到一个更小的匹配大小(两个1和两个0)
downsampled_df = clean_df.groupby("label").sample(2)print(downsampled_df) id label4 f38a6374c348f90b587e046aac6079959adf3835 05 068aba587a4950175d04c680d38943fd488d6a9d 01 a24ce148f6ffa7ef8eefb4efb12ebffe8dd700da 10 c18f2d887b7ae4f6742ee445113fa1aef383ed77 1