【问题标题】:How to remove, randomly, rows from a dataframe but from each label?如何从数据框中但从每个标签中随机删除行?
【发布时间】:2017-04-25 08:17:55
【问题描述】:

这是一个机器学习项目。

我有一个数据框,其中 5 列作为特征,1 列作为标签(图 A)。

我想从每个标签中随机删除 2 行。 所以,因为有 12 行(每个标签 4 行);我最终会得到 6 行(每个标签 2 行)(图 B)。

我该怎么做?仅使用 numpy 会更容易吗?

图A

图B

这是我的代码:

# THIS IS FOR FIGURE A
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(12, 5))

label=np.array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3])

df['label'] = label
df.index=['s1', 's1', 's1', 's1', 's2', 's2', 's2', 's2', 's3', 's3', 's3', 's3']
df

#THIS IS MY ATTEMPT FOR FIGURE B
dfs = df.sample(n=2)
dfs

【问题讨论】:

  • 我认为 sklearn 有 kfold 分层抽样。在使用 pandas 之前,请考虑留在 sklearn 中。 Sklearn 有很多内置函数来处理这样的事情。你当然可以使用 pandas,但除非你必须这样做,否则不要使用它。
  • 我想绘制在增加样本(行)数量时准确性如何变化的图。所以删除的行将被发送到分类器和交叉验证。因此,一种选择是使用 Pandas,另一种选择是使用 numpy。你知道如何使用数组来处理 numpy 吗?

标签: python python-3.x pandas numpy machine-learning


【解决方案1】:

使用 groupby.apply:

df.groupby('label', as_index=False).apply(lambda x: x.sample(2)) \
                                   .reset_index(level=0, drop=True)
Out: 
           0         1         2         3         4  label
s1  0.433731  0.886622  0.683993  0.125918  0.398787      1
s1  0.719834  0.435971  0.935742  0.885779  0.460693      1
s2  0.324877  0.962413  0.366274  0.980935  0.487806      2
s2  0.600318  0.633574  0.453003  0.291159  0.223662      2
s3  0.741116  0.167992  0.513374  0.485132  0.550467      3
s3  0.301959  0.843531  0.654343  0.726779  0.594402      3

在我看来,更简洁的方法是理解:

pd.concat(g.sample(2) for idx, g in df.groupby('label'))

这将产生相同的结果:

           0         1         2         3         4  label
s1  0.442293  0.470318  0.559764  0.829743  0.146971      1
s1  0.603235  0.218269  0.516422  0.295342  0.466475      1
s2  0.569428  0.109494  0.035729  0.548579  0.760698      2
s2  0.600318  0.633574  0.453003  0.291159  0.223662      2
s3  0.412750  0.079504  0.433272  0.136108  0.740311      3
s3  0.462627  0.025328  0.245863  0.931857  0.576927      3

【讨论】:

【解决方案2】:

这是一个非常简单的方法。将所有行与sample(frac=1) 混合,然后找到每个标签的累积计数并选择值为 1 或更少的那些。

df.loc[df.sample(frac=1).groupby('label').cumcount() <= 1]

这里是 sklearn 的分层 kfold。示例taken from here

from sklearn.model_selection import StratifiedKFold
X = df[[0,1,2,3,4]]
y = df.label
skf = StratifiedKFold(n_splits=2)

for train_index, test_index in skf.split(X, y):
    X_train, X_test = X.loc[train_index], X.loc[test_index]
    y_train, y_test = y[train_index], y[test_index]

print(X_train)

          0         1         2         3         4
0  0.656240  0.904032  0.256067  0.916293  0.262773
1  0.526509  0.555683  0.667756  0.208831  0.699438
4  0.096499  0.688737  0.328670  0.260733  0.834091
5  0.320150  0.602197  0.793404  0.911291  0.269915
8  0.913669  0.171831  0.534418  0.862583  0.994561
9  0.718337  0.256351  0.348813  0.420952  0.622890

print(y_train)

0    1
1    1
4    2
5    2
8    3
9    3

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
  • 2021-11-30
  • 2018-10-04
  • 2021-01-08
相关资源
最近更新 更多