Let's break down the task step by step.
- Separate the data for the different particles:
GatherBy
- Sort data by frame number (not really necessary as it's sorted, but let's do it anyway):
SortBy
- Extract the positions and calculate the MSD.
I have your data stored in the variable data
.
GatherBy[data, First]
separates into sublists having the same first element (same particle). Let's take the first sublist, sublist = First@GatherBy[data, First]
.
sublist = SortBy[sublist, #[[2]]&]
sorts the sublist by the second element (frame number).
Now take the difference of sequential coordinates, take the squared norm of that difference, and calculate the mean: Mean[#.#& /@ sublist]sublist[[All, {3,4}]] ]
.
Putting it all together:
gatheredData = GatherBy[data, First];
msd = Function[sublist,
Mean[#.# & /@
Differences@SortBy[sublist, #[[2]] &][[All, {3, 4}]]
]
] /@ gatheredData
You may wish to pair up this list of results with the particle indices:
Transpose[{gatheredData[[All, 1, 1]], msd}]
(* ==> {{1., 0.513101}, {2., 2.69401}, {3., 0.887661}} *)
Again, this is not necessary if your list was originally sorted by particle index, but it's important if it wasn't.
Recommended reading to understand this code: