我有一个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中实现这一目标?
我还有大量的数据,所以我正在寻找最快的方法。
答案 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 的“替代”值。