我需要有关编程模式的建议以及DataFrame对我们数据的使用。我们有数以千计的小型ASCII文件是粒子追踪实验的结果(详见www.openptv.net)。每个文件都是在该时间实例中标识和跟踪的粒子列表。文件名是帧的编号。例如:
ptv_is.10000(即第10000号帧)
prev next x y z
-1 5 0.0 0.0 0.0
0 0 1.0 1.0 1.0
1 1 2.0 2.0 2.0
2 2 3.0 3.0 3.0
3 -2 4.0 4.0 4.0
ptv_is.10001(即下一个时间范围,10001)
1 2 1.1 1.0 1.0
2 8 2.0 2.0 2.0
3 14 3.0 3.0 3.0
4 -2 4.0 4.0 4.0
-1 3 1.5 1.12 1.32
0 -2 0.0 0.0 0.0
ASCII文件的列是:prev - 是前一帧中粒子的行号,next是下一帧中粒子的行号,x,y,z是粒子的坐标。如果'prev'的行索引为-1 - 粒子出现在当前帧中,并且没有及时链接。如果'next'是-2,则粒子没有及时前进的链接,并且轨迹在此帧中结束。
因此我们将这些文件读入具有相同列标题的单个DataFrame中,并添加时间索引,即帧编号
prev next x y z time
-1 5 0.0 0.0 0.0 10000
0 0 1.0 1.0 1.0 10000
1 1 2.0 2.0 2.0 10000
2 2 3.0 3.0 3.0 10000
3 -2 4.0 4.0 4.0 10000
1 2 1.1 1.0 1.0 10001
2 8 2.0 2.0 2.0 10001
3 14 3.0 3.0 3.0 10001
4 -2 4.0 4.0 4.0 10001
-1 3 1.5 1.12 1.32 10001
0 -2 0.0 0.0 0.0 10001
现在,我发现很难找到使用DataFrame的最佳方法。如果我们可以添加一个名为trajectory_id的附加列,我们以后可以按时间重新索引此DataFrame(在单个时间实例中创建粒子的子组并了解它们的空间分布)或者通过轨迹_id然后创建轨迹(或链接粒子并了解它们在空间中的时间演变,例如x(t),y(t),z(t)对于相同的轨迹_id)。
如果输入为:
prev next x y z time
-1 5 0.0 0.0 0.0 10000
0 0 1.0 1.0 1.0 10000
1 1 2.0 2.0 2.0 10000
2 2 3.0 3.0 3.0 10000
3 -2 4.0 4.0 4.0 10000
1 2 1.1 1.0 1.0 10001
2 8 2.0 2.0 2.0 10001
3 14 3.0 3.0 3.0 10001
4 -2 4.0 4.0 4.0 10001
-1 3 1.5 1.12 1.32 10001
0 -2 0.0 0.0 0.0 10001
然后我需要的结果是:
prev next x y z time trajectory_id
-1 5 0.0 0.0 0.0 10000 1
0 0 1.0 1.0 1.0 10000 2
1 1 2.0 2.0 2.0 10000 3
2 2 3.0 3.0 3.0 10000 4
3 -2 4.0 4.0 4.0 10000 -999
1 2 1.1 1.0 1.0 10001 2
2 8 2.0 2.0 2.0 10001 3
3 14 3.0 3.0 3.0 10001 4
-1 -2 4.0 4.0 4.0 10001 -999
-1 3 1.5 1.1 1.3 10001 5
0 -2 0.0 0.0 0.0 10001 1
表示:
prev next x y z time trajectory_id
-1 5 0.0 0.0 0.0 10000 1 < - appeared first time, new id
0 0 1.0 1.0 1.0 10000 2 < - the same
1 1 2.0 2.0 2.0 10000 3 <- the same
2 2 3.0 3.0 3.0 10000 4 <- the same
3 -2 4.0 4.0 4.0 10000 -999 <- sort of NaN, there is no link in the next frame
1 2 1.1 1.0 1.0 10001 2 <- from row #1 in the time 10000, has an id = 2
2 8 2.0 2.0 2.0 10001 3 <- row #2 at previous time, has an id = 3
3 14 3.0 3.0 3.0 10001 4 < from row # 3, next on the row #14, id = 4
-1 -2 4.0 4.0 4.0 10001 -999 <- but linked, marked as NaN or -999
-1 3 1.5 1.1 1.3 10001 5 <- new particle, new id = 5 (new trajectory_id)
0 -2 0.0 0.0 0.0 10001 1 <- from row #0 id = 1
希望这能更好地解释我正在寻找的东西。唯一的问题是我不知道如何通过DataFrame表的行创建滚动函数,创建一个新的索引列,轨迹_id。
例如,带有列表的简单应用程序如下所示:
http://nbviewer.ipython.org/7020209
感谢大熊猫使用的每一个提示, 亚历
答案 0 :(得分:1)
纯!这个问题很贴近我的心;我也使用pandas for particle tracking。这不是我所处理的完全相同的问题,但这是一个未经测试的草图,它提供了一些有用的熊猫习语。
results = []
first_loop = True
next_id = None
for frame_no, frame in pd.concat(list_of_dataframes).groupby('time'):
if first_loop:
frame['traj_id'] = np.arange(len(frame))
results.append(frame)
next_id = len(frame)
first_loop = False
continue
prev_frame = results[-1]
has_matches = frame['prev'] > 0 # boolean indexer
frame[has_matches]['traj_'id'] = prev_frame.iloc[frame[has_matches]['prev']]
count_unmatched = (~has_matches).sum()
frame[~has_matches]['traj_'id'] = np.arange(next_id, next_id + count_unmatched)
next_id += count_unmatched
results.append(frame)
pd.concat(results)
答案 1 :(得分:0)
如果我理解得很好,你想跟踪时间中粒子在太空中的位置。您正在处理五维数据,因此可能是DataFrame,它不是您问题的最佳结构,您可能会考虑面板结构或减少数据。
取一个粒子,你有两个可能性,首先将坐标视为三个不同的值,因此你需要三个字段或将它们视为一个整体,例如元组或点对象。 在第一种情况下,您有时间加上三个值,因此您有四个轴,您需要一个DataFrame。在第二种情况下,您有两个轴,因此您可以使用系列。
对于多个粒子,只需使用particle_id并将所有DataFrame放入Panel或将系列放入DataFrame中。
一旦您知道要使用哪种数据结构,就可以将数据放入。
按顺序读取文件并制作一组“实时”粒子,例如:
{particle_id1: { time1: (x1,y1,z1), time2: (x2,y2,z2), ...}, ...}
当检测到一个新粒子时(上一个-1)分配一个新的particle_id并放入该集合。当粒子'deads'从集合中弹出并将数据放入Series中,然后将此Series添加到粒子DataFrame(或DataFrame / Panel)。
您还可以创建粒子ID索引和下一个字段以帮助识别ID:
{ next_position_of_last_file: particle_id, ... }
或
{ position_in_last_file: particle_id, ...}