10

我有一个数据框:

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 次,其中最小值sec1,最大值sec7。此外,我想得到这个转换第一次发生的位置为a->b0。对于transition_index列,我考虑转换的第一个值,即a计算的索引和最小值,最大值,我取转换的第二个值,即值 at 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 中实现这一点?

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

4

2 回答 2

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
于 2020-07-26T18:13:00.963 回答
1

从添加具有先前IDsec值的列开始:

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)

现在,如果您运行此函数,例如查找从ab的转换:

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

你会得到:

(3, 1, 7)

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

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

于 2020-07-26T18:06:18.160 回答