随机抽样Pandas中数据帧的子集

时间:2016-06-28 20:17:47

标签: python pandas sample random-sample

假设我有一个包含100,000个条目的数据框,并希望将其拆分为1000个条目的100个部分。

如何随机抽取100个部分中只有一部分的50个随机样本。数据集已经被排序,前1000个结果是下一个部分的第一个部分,依此类推。

非常感谢

5 个答案:

答案 0 :(得分:26)

您可以使用sample方法*:

In [11]: df = pd.DataFrame([[1, 2], [3, 4], [5, 6], [7, 8]], columns=["A", "B"])

In [12]: df.sample(2)
Out[12]:
   A  B
0  1  2
2  5  6

In [13]: df.sample(2)
Out[13]:
   A  B
3  7  8
0  1  2

* 在其中一个DataFrame上。

注意:如果您的样本量较大,那么DataFrame的大小会引发错误,除非您使用替换进行采样。

In [14]: df.sample(5)
ValueError: Cannot take a larger sample than population when 'replace=False'

In [15]: df.sample(5, replace=True)
Out[15]:
   A  B
0  1  2
1  3  4
2  5  6
3  7  8
1  3  4

答案 1 :(得分:5)

一种解决方案是使用numpy中的choice函数。

假设您想要100个中的50个条目,您可以使用:

import numpy as np
chosen_idx = np.random.choice(1000, replace=False, size=50)
df_trimmed = df.iloc[chosen_idx]

这当然不考虑您的块结构。例如,如果您想要块i中的50个项目样本,则可以执行以下操作:

import numpy as np
block_start_idx = 1000 * i
chosen_idx = np.random.choice(1000, replace=False, size=50)
df_trimmed_from_block_i = df.iloc[block_start_idx + chosen_idx]

答案 2 :(得分:2)

谢谢你,杰夫, 但是我收到一个错误;

AttributeError: Cannot access callable attribute 'sample' of 'DataFrameGroupBy' objects, try using the 'apply' method

所以我建议使用以下命令代替 sample = df.groupby("section").sample(50)

df.groupby('section').apply(lambda grp: grp.sample(50))

答案 3 :(得分:1)

您可以向数据中添加 "section" 列,然后执行分组和采样:

import numpy as np
import pandas as pd

df = pd.DataFrame(
    {"x": np.arange(1_000 * 100), "section": np.repeat(np.arange(100), 1_000)}
)
# >>> df
#            x  section
# 0          0        0
# 1          1        0
# 2          2        0
# 3          3        0
# 4          4        0
# ...      ...      ...
# 99995  99995       99
# 99996  99996       99
# 99997  99997       99
# 99998  99998       99
# 99999  99999       99
#
# [100000 rows x 2 columns]

sample = df.groupby("section").sample(50)
# >>> sample
#            x  section
# 907      907        0
# 494      494        0
# 775      775        0
# 20        20        0
# 230      230        0
# ...      ...      ...
# 99740  99740       99
# 99272  99272       99
# 99863  99863       99
# 99198  99198       99
# 99555  99555       99
#
# [5000 rows x 2 columns]

附加 .query("section == 42") 或任何您只对特定部分感兴趣的内容。

请注意,这需要 pandas 1.1.0,请参阅此处的文档:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.core.groupby.DataFrameGroupBy.sample.html

对于旧版本,请参阅@msh5678 的答案

答案 4 :(得分:0)

这是递归的好地方。

def main2():
    rows = 8  # say you have 8 rows, real data will need len(rows) for int
    rands = []
    for i in range(rows):
        gen = fun(rands)
        rands.append(gen)
    print(rands)  # now range through random values


def fun(rands):
    gen = np.random.randint(0, 8)
    if gen in rands:
        a = fun(rands)
        return a
    else: return gen


if __name__ == "__main__":
    main2()

output: [6, 0, 7, 1, 3, 5, 4, 2]