用熊猫首次出现的索引计算过渡的最小值和最大值

时间:2020-07-26 17:51:52

标签: python pandas numpy

我有一个DataFrame:

df = pd.DataFrame({'ID':['a','b','d','d','a','b','c','b','d','a','b','a'], 
                   'sec':[3,6,2,0,4,7,10,19,40,3,1,2]})
print(df)
   ID  sec
0   a    3
1   b    6
2   d    2
3   d    0
4   a    4
5   b    7
6   c   10
7   b   19
8   d   40
9   a    3
10  b    1
11  a    2

我想计算转换发生了多少次。在ID列中,a->b类似于b->d, d->d, d->a, b->c, c->b, b->a被视为过渡。我可以使用Counter来做到这一点,

Counter(zip(df['ID'].to_list(),df['ID'].to_list()[1:]))
Counter({('a', 'b'): 3,
         ('b', 'd'): 2,
         ('d', 'd'): 1,
         ('d', 'a'): 2,
         ('b', 'c'): 1,
         ('c', 'b'): 1,
         ('b', 'a'): 1})

我还需要获取这些转换的sec列的最小值和最大值。例如,这里a->b已发生3次,其中最小sec值为1,最大sec值为7。另外,我想获得a->b的0首次发生过渡的位置。对于transition_index列,我考虑过渡的第一个值,即a的索引,并计算最小值,最大值是过渡的第二个值,即b的值。

这是我想要获得的最终输出:

df = pd.DataFrame({'ID_1':['a','b','d','d','b','c','b'], 
                   'ID_2':['b','d','d','a','c','b','a'],
                   'sec_min':[1,2,0,3,10,19,2],
                   'sec_max':[7,40,0,4,10,19,2],
                   'transition_index':[0,1,2,3,5,6,10],
                   'count':[3,2,1,2,1,1,1]})
print(df)
  ID_1 ID_2  sec_min  sec_max  transition_index  count
0    a    b        1        7                 0      3
1    b    d        2       40                 1      2
2    d    d        0        0                 2      1
3    d    a        3        4                 3      2
4    b    c       10       10                 5      1
5    c    b       19       19                 6      1
6    b    a        2        2                10      1

如何在Python中实现这一目标?

我还有大量的数据,所以我正在寻找最快的方法。

2 个答案:

答案 0 :(得分:10)

您具有from -> to形式的转换。 'transition_index'基于“ from”行的索引,而'sec'聚合则基于与“ to”行关联的值。

我们可以移动ID上的索引和组,并移动ID,从而使我们可以使用带有命名聚合的单个groupby来获得所需的输出。


df = df.reset_index()
df['index'] = df['index'].shift().astype('Int64')

(df.groupby([df['ID'].shift(1).rename('ID_1'), df['ID'].rename('ID_2')], sort=False)
   .agg(sec_min=('sec', 'min'),
        sec_max=('sec', 'max'),
        transition_index=('index', 'first'),
        count=('sec', 'size'))
   .reset_index()
)

  ID_1 ID_2  sec_min  sec_max  transition_index  count
0    a    b        1        7                 0      3
1    b    d        2       40                 1      2
2    d    d        0        0                 2      1
3    d    a        3        4                 3      2
4    b    c       10       10                 5      1
5    c    b       19       19                 6      1
6    b    a        2        2                10      1

答案 1 :(得分:1)

从添加以前值为 ID sec 的列开始:

df['prevID']  = df.ID.shift(fill_value='')
df['prevSec'] = df.sec.shift(fill_value=0)

然后定义以下功能:

def find(df, IDfrom, IDto):
    rows = df.query('prevID == @IDfrom and ID == @IDto')
    tbl = rows.loc[:, ['prevSec', 'sec']].values
    n = rows.index.size
    return (n, tbl.min(), tbl.max()) if n > 0 else (n, 0, 0)

现在,如果您运行此功能,例如从 a 查找过渡 到 b

find(df, 'a', 'b')

您将得到:

(3, 1, 7)

然后为所有其他 from to 值调用此函数。

请注意,即使没有此函数,该函数也会返回正确的结果 给定值之间的转换。当然,您可以选择其他 如果未找到过渡,则为 min max 的“替代”值。