繁体   English   中英

用python(simil触发器)使用2个不同的数组拖动值

[英]Drag value using 2 different array with python (simil flip flop)

我想从2个不同的数组中获取一个新数组(名为Result),其中:

0 _ 0 => Hold state
1 _ 0 => 1
0 _ 1 => 0
1 _ 1 => 0

例:

array1  array2  Result
     0       0       0
     0       1       0
     1       1       0
     1       0       1
     0       0       1
     0       0       1
     1       0       1
     0       0       1
     1       1       0
     0       0       0
     0       1       0
     0       0       0
     1       0       1
     0       0       1

它就像Latch SR Flip Flop设备唯一的区别是1 1 => 0

我想用熊猫或numpy。 谢谢您的帮助。 我写了这个并且它有效,但它太慢了。

def FLIP(array1, array2):

    assert array1.index.equals(array2.index), 'Indices do not match'
    array = pd.Series(False, dtype=bool, index=array1.index)
    i = 0
    while i < len(array1):
        if array1[i]:
            array[i] = True
            for j in xrange(i, len(array2)):
                if array2[j]:
                    array[j] = False
                    break
                array[j] = True
            i = j
        i += 1
    return array.fillna(value=False)

您可以使用pandas forward fill函数来避免对数据进行python循环。

除了“保持状态”部分,其余部分基本上是按位移位。

例如:

import pandas as pd

array1 = [0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]
array2 = [0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0]

expected = [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]

def flip(series1, series2):
    series1, series2 = pd.Series(series1), pd.Series(series2)

    out = pd.Series(np.nan, series1.index)
    out[:] = (series1 >> series2).astype(int)
    out[(series1 == 0) & (series2 == 0)] = np.nan
    return out.ffill()

print flip(array1, array2).values
print expected

请注意,这会使起始值保持未定义状态。 如果您愿意,可以用任何有意义的值填充它(例如0)。

如果我理解正确,我们可以利用pandas如何处理nan来处理“保持”逻辑:

def flipper(a1, a2):
    res = pd.Series(index=a1.index) 
    res.loc[a1 == 1] = 1
    res.loc[a2 == 1] = 0
    res = res.ffill().fillna(0)
    return res

这给出了测试用例的预期结果:

>>> df
    array1  array2  Result  result_computed
0        0       0       0                0
1        0       1       0                0
2        1       1       0                0
3        1       0       1                1
4        0       0       1                1
5        0       0       1                1
6        1       0       1                1
7        0       0       1                1
8        0       1       0                0
9        0       0       0                0
10       0       1       0                0
11       0       0       0                0
12       1       0       1                1
13       0       0       1                1

并且似乎与您的输出一般匹配:

from itertools import product

def check():
    for w in range(1, 9):
        for a0 in product(range(2), repeat=w):
            for a1 in product(range(2), repeat=w):
                s0, s1 = pd.Series(a0), pd.Series(a1)
                flipper_result = flipper(s0, s1)
                FLIP_result = FLIP(s0, s1)
                assert (flipper_result == FLIP_result).all()
    return True

>>> check()
True

使用DataFrame.merge 这似乎比提供的方法快得多。 在10,000个元素的数组上,它的速度提高了约50倍。 在10 ^ 6阵列上,耗时220ms。

In [80]: data = pd.DataFrame({
   ....:     'array1': [0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0],
   ....:     'array2': [0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
   ....: })

In [81]: flipflop = pd.DataFrame({
   ....:     'array1': [0, 1, 0, 1],
   ....:     'array2': [0, 0, 1, 1],
   ....:     'Result': [pd.np.nan, 1, 0, 0]
   ....: })

In [82]: data.merge(flipflop, how='left', on=['array1', 'array2']).ffill().fillna(0)
Out[82]:
    array1  array2  Result
0        0       0       0
1        0       1       0
2        1       1       0
3        1       0       1
4        0       0       1
5        0       0       1
6        1       0       1
7        0       0       1
8        0       1       0
9        0       0       0
10       0       1       0
11       0       0       0
12       1       0       1
13       0       0       1

In [83]: data = pd.DataFrame({
   ....:     'array1': pd.np.random.random_integers(0, 1, 10000),
   ....:     'array2': pd.np.random.random_integers(0, 1, 10000),
   ....: })

In [84]: %timeit FLIP(data.array1, data.array2)
10 loops, best of 3: 168 ms per loop

In [85]: %timeit data.merge(flipflop, how='left', on=['array1', 'array2']).ffill().fillna(0)
100 loops, best of 3: 2.97 ms per loop

你正在寻找的结果是依赖于历史的,所以我不知道避免两个数组上的循环的余地。

def flip(array1, array2):

    currentstate = 0
    result = []

    for i, j in zip(array1, array2):

        if (i < j):

            currentstate = 0

        if (j < i):

            currentstate = 1

        result.append(currentstate)

    return np.array(result)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM