我想通过'pd.sample'方法随机化我的DataFrame,但是为了实现条件采样。我需要结果满足以下条件:某些列中没有相同的两个连续行的值。
e.g.: A B
a 2
b 3
c 3
d 4
我希望样本结果如
e.g. A B
a 2
c 3
d 4
b 3
(即B保持相同值的行不会连续)
我怎样才能做到这一点?我已经有了下面的东西,但作为一个新手,我不熟悉编写循环句子:
def compareSyllable(data):
for i in data:
(data['B'] != data['B'].shift()).any()
while compareSyllable(data) == True:
for i in range(data):
data_final=data.sample(frac=1)
答案 0 :(得分:2)
compare_syllable
我使用values属性来获取numpy数组。这种比较的语法更清晰。和IIUC一样,您不希望在任何列中从一行到下一行匹配任何值。因此,在numpy数组上使用all
会自动检查数组中的每个值。
conditional_sample
我做了这个,这样你就可以通过pd.DataFrame.sample
实际传递你想要的任何参数pd.DataFrame.pipe
。我还参数化了条件采样所依赖的谓词。意思是,你可以创建其他条件函数来传递以适应其他目的。
pd.DataFrame.pipe
pipe
是一个DataFrame方法,其第一个参数是可调用的。 pipe
传递给该可调用对象作为其第一个参数,即调用pipe
的相同DataFrame。其余的参数传递给callable。
def compare_syllable(data):
v = data.values
return (v[:-1] != v[1:]).all()
def conditional_sample(df, predicate, *args, **kwargs):
d = df.sample(*args, **kwargs)
while not predicate(d):
d = df.sample(*args, **kwargs)
return d
df.pipe(conditional_sample, compare_syllable, frac=1)
A B
2 c 3
0 a 2
1 b 3
3 d 4
我还要指出pipe
是我的选择,我们也可以通过这种更正常的方式调用它:
conditional_sample(
df=df,
predicate=compare_syllable,
frac=1
)
A B
2 c 3
0 a 2
3 d 4
1 b 3
为了进一步证明我们可以传递其他参数,我会放弃frac=1
参数并传递3
而不是样本的行数
df.pipe(conditional_sample, compare_syllable, 3)
A B
1 b 3
0 a 2
3 d 4
这也符合条件。
包含无限循环处理的版本
from itertools import count, islice
def compare_syllable(data):
v = data.values
return (v[:-1] != v[1:]).all()
def conditional_sample(df, predicate, limit=None, **kwargs):
"""default limit of None is infinite limit"""
d = df.sample(**kwargs)
for i in islice(count(), limit):
if predicate(d):
return d
break
else:
d = df.sample(**kwargs)
df.pipe(conditional_sample, compare_syllable, limit=10, frac=1)
A B
2 c 3
3 d 4
1 b 3
0 a 2