【问题标题】:How to select records randomly from the DataFrame?如何从 DataFrame 中随机选择记录?
【发布时间】:2019-02-14 04:49:05
【问题描述】:

我有以下单列 pandas DataFrame,名为 y。该列称为0(零)。

y =

1
0
0
1
0
1
1
2
0
1
1
2
2
2
2
1
0
0

我想为每个 y 值选择 N 行记录索引。在上面的例子中,0 有 6 条记录,1 有 7 条记录,2 有 5 条记录。 我需要从这 3 个组中的每一个中选择 4 条记录。

下面我提供我的代码。但是,此代码始终选择每个类的 first N(例如 4)条记录。我需要在整个数据集上随机进行选择。

我该怎么做?

idx0 = []
idx1 = []
idx2 = []

for i in range(0, len(y[0])):
    if y[0].iloc[i]==0 and len(idx0)<=4:
        idx0.append(i)
    if y[0].iloc[i]==1 and len(idx1)<=4:
        idx1.append(i)
    if y[0].iloc[i]==2 and len(idx2)<=4:
        idx2.append(i)

更新:

预期结果是索引列表,而不是过滤后的 DataFrame y

n = 4
a = y.groupby(0).apply(lambda x: x.sample(n)).reset_index(1).\
    rename(columns={'level_1':'indices'}).reset_index(drop=True).groupby(0)['indices'].\
                                                    apply(list).reset_index()

class = 0
idx = a.ix[2].tolist()[class]
y.values[idx]   # THIS RETURNS WRONG WRONG CLASSES IN SOME CASES

0
1. # <- WRONG
0
0

【问题讨论】:

  • 为什么需要索引,而不是随机样本?
  • @ALollz:我需要在我的代码中使用它作为参考。
  • 嗯,是的,我只是不知道您是否需要它来重新索引或执行一些可以使用.sample 一次性完成的计算。此外,如果一个组的行数少于 N 行(如上例中的 3),您应该只获取 3 的索引,还是希望最多替换 4 个元素进行采样?
  • @ALollz:这个问题可以忽略。 N 总是大于每个类的记录数。

标签: python pandas


【解决方案1】:

groupby()df.sample() 一起使用:

n=4
df.groupby('Y').apply(lambda x: x.sample(n)).reset_index(drop=True)

    Y
0   0
1   0
2   0
3   0
4   1
5   1
6   1
7   1
8   2
9   2
10  2
11  2

编辑,索引:

df.groupby('Y').apply(lambda x: x.sample(n)).reset_index(1).\
    rename(columns={'level_1':'indices'}).reset_index(drop=True).groupby('Y')['indices'].\
                                                    apply(list).reset_index()

   Y          indices
0  0   [4, 1, 17, 16]
1  1    [0, 6, 10, 5]
2  2  [13, 14, 7, 11]

【讨论】:

  • 我应该收到索引列表。你能更新你的解决方案吗?谢谢。
  • 好的,谢谢。但我需要获取每个类的索引,就像它在我的代码中一样:idx0idx1idx2
  • @ScalaBoy 立即查看。认为这是你想要的
  • 它有效。谢谢!例如,要获得 idx0 作为 numpy 数组,我应该将代码的结果保存在 df2 中并执行 idx0 = df2.ix[0].tolist() 吗?我怎样才能得到这种类型的数组 idx0 = [2,3,1,5] ?
  • @ScalaBoy, df2.values 你的意思是?
【解决方案2】:

使用

idx0,idx1,idx2=[ np.random.choice(y.index.values,4,replace=False).tolist()for _, y in df.groupby('0')]
idx0
Out[48]: [1, 2, 16, 8]

详细一点

s=pd.Series([1,0,1,0,2],index=[1,3,4,5,9])
idx=[1,4] # both anky and mine answer return the index
s.loc[idx] # using .loc with index is correct 
Out[59]: 
1    1
4    1
dtype: int64
s.values[idx]# using value with slice with index, is wrong
Out[60]: array([0, 2], dtype=int64)

【讨论】:

  • 在我的真实数据集中,这个解决方案混合了类。当我执行 y.values[idx0] 时,我看到了一些类 1 的记录,而应该只有 0 类记录。
  • @ScalaBoy 当你提到索引时,你应该使用 .loc,而不是 values[idx0],它应该是 y.loc[idx0],这就是你否决我的解决方案的原因?跨度>
  • @ScalaBoy 你的问题怎么样?如果更改为 .loc ,返回预期的输出?
【解决方案3】:

假设列“y”属于数据框“df”,并且您要选择 N=4 随机行:

for i in np.unique(df.y).astype(int):
    print(df.y[np.random.choice(np.where(df.y==np.unique(df.y)[i])[0],4)])

你会得到:

10116    0
329      0
4709     0
5630     0
Name: y, dtype: int32
382     1
392     1
9124    1
383     1
Name: y, dtype: int32
221      2
443      2
4235     2
5322     2
Name: y, dtype: int32

已编辑,获取索引:

pd.concat([df.y[np.random.choice(np.where(df.y==np.unique(df.y)[i])[0],4)] for i in np.unique(df.y).astype(int)],axis=0)

你会得到:

10116    0
329      0
4709     0
5630     0
382      1
392      1
9124     1
383      1
221      2
443      2
4235     2
5322     2
Name: y, dtype: int32

获取嵌套的索引列表:

[df.holiday[np.random.choice(np.where(df.holiday==np.unique(df.holiday)[i])[0],4)].index.tolist() for i in np.unique(df.holiday).astype(int)]

你会得到:

[[10116,329,4709,5630],[382,392,9124,383],[221,443,4235,5322]]

【讨论】:

  • 我需要获取索引。
  • 请立即查看
  • 此代码返回给我不同数量的 0、1 和 2 记录。
  • 每个类的列是否有足够数量的记录(n>=4)?
  • 是的,总是这样。我需要在idx0idx1idx2 中分别获取类的索引,
【解决方案4】:
N = 4
y.loc[y[0]==0].sample(N)
y.loc[y[0]==1].sample(N)
y.loc[y[0]==2].sample(N)

【讨论】:

    猜你喜欢
    • 2011-09-05
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 2015-01-26
    相关资源
    最近更新 更多