我有一个包含100,000行数据的 pandas DataFrame
,想把它分成100个部分,每部分有1000行。
我该如何在这100个部分中随机抽取一部分的特定大小(例如50行)?由于df已经按照顺序排列,所以前1000行来自第一部分,下一个1000行来自另一部分,以此类推。
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
*关于DataFrames之一的部分。
注意:如果您的样本大小大于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
replace
函数是做什么用的?文档里写得不太清楚,请解释一下。谢谢! - hoang tran一种解决方案是使用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]
"section"
列,然后执行 groupby 和 sample: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 的答案。
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))
这是一个递归的好地方。
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()
输出:[6, 0, 7, 1, 3, 5, 4, 2]
df.iloc[np.random.randint(1,1000,50),:]
。df1
是其中的 100 个部分之一。 - Abdou