Pandas 中数据帧子集的随机样本
Random Sample of a subset of a dataframe in Pandas
假设我有一个包含 100,000 个条目的数据框,我想将它分成 100 个部分,每部分 1000 个条目。
我如何从 100 个部分中的一个部分中随机抽取 50 个样本。数据集已经排序,因此前 1000 个结果是第一部分,下一部分是下一部分,依此类推。
非常感谢
一种解决方案是使用 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]
可以使用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
这是递归的好地方。
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]
您可以向数据中添加一个 "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 的回答
谢谢你,杰夫,
但是我收到一个错误;
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))
假设我有一个包含 100,000 个条目的数据框,我想将它分成 100 个部分,每部分 1000 个条目。
我如何从 100 个部分中的一个部分中随机抽取 50 个样本。数据集已经排序,因此前 1000 个结果是第一部分,下一部分是下一部分,依此类推。
非常感谢
一种解决方案是使用 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]
可以使用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
这是递归的好地方。
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]
您可以向数据中添加一个 "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 的回答
谢谢你,杰夫, 但是我收到一个错误;
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))