Using a nested loop seems a bit too much IMHO.
I would propose something around these lines, using only the functionality from the raster package:
#load package
library(raster)
# create dataframe
df <- data.frame(id=c('a','b','c'), lat=c(51.50549,37.80248,51.50609), lon= c(-0.0924609,-122.416634,-0.1238904))
Now, since these are point locations with Latitude and Longitude, I'm creating a projection string with a geographic coordinate system:
pj <- CRS('+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0')
I think the cleanest way would be to define a little function which does exactly what you want (I call it getPoints):
getPoints <- function(df,id){
  refpoint <- SpatialPoints(df[df$id==id,3:2],proj4string=pj)
  pdist <- pointDistance(refpoint,SpatialPoints(df[,3:2],proj4string=pj),lonlat = T)
  return(df[pdist < 5000,])
}
To calculate the distance between points, I'm using the pointDistance from the raster package. Before/while calculating the distance, I need to convert the coordinates into spatial points with SpatialPoints and the defined projection pj. I'm selecting the reference point refpoint with the idsupplied to the function and calculate the distance to all points in the dataframe df. I'm also calculating the distance to the point itself, so I can index all points with the condition pdist <= 500000 and it will also return the selected point (since the distance is 0).
On a sidenote, I could have avoided assigning the refpoint to a variable, but it's a bit clearer like this.
Finally you could either loop over your point locations
for (id_sel in df$id){
print(getPoints(df,id_sel))
}
or use lapply, which will conveniently save my results to a list and avoid looping in general:
lapply(df$id,function(x) getPoints(df,x))