在对pandas中的整个DataFrame进行采样时,避免在连续列中使用两个相同的值

时间:2018-03-14 05:22:36

标签: python pandas dataframe random sample

我想通过'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)

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