假设我有一个包含100,000个条目的数据框,并希望将其拆分为1000个条目的100个部分。
如何随机抽取100个部分中只有一部分的50个随机样本。数据集已经被排序,前1000个结果是下一个部分的第一个部分,依此类推。
非常感谢答案 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]