Building GeoDataFrame row by row

You don't need to build the GeoDataFrame row by row here, look at pandas.DataFrame.from_dict¶

import pandas as pd
df = pd.DataFrame.from_dict(my_dict,orient='index')
     name     lat        lon    type
007    A  48.843664   2.302672   small
008    B  50.575813   7.258148  medium
010    C  47.058420  15.437464     big
from shapely.geometry import Point
df["geometry"] = df.apply (lambda row: Point(row.lon,, axis=1)

Convert to a GeoDataFrame

gdf = gpd.GeoDataFrame(df, geometry=df.geometry)
     name    lat        lon      type            geometry
007    A  48.843664   2.302672   small  POINT (2.302672 48.843664)
008    B  50.575813   7.258148  medium  POINT (7.258148 50.575813)
010    C  47.058420  15.437464     big  POINT (15.437464 47.05842)

Or directly:

gdf = gpd.GeoDataFrame(df, geometry=df.apply(lambda row: Point(row.lon,, axis=1)

In other words, do not form a new DataFrame for each row. Instead, collect all the data in a list of dicts, and then call df = pd.DataFrame(data) once at the end, outside the loop.
Each call to df.append requires allocating space for a new DataFrame with one extra row, copying all the data from the original DataFrame into the new DataFrame, and then copying data into the new row. All that allocation and copying makes calling df.append in a loop very inefficient. The time cost of copying grows quadratically with the number of rows. Not only is the call-DataFrame-once code easier to write, it's performance will be much better -- the time cost of copying grows linearly with the number of rows. (from How to append rows in a pandas dataframe in a for loop?)

I don't think that a row by row building would have better performance. I've tested.


import geopandas as gpd
import pandas as pd
from shapely.geometry import  Point

d = {'007': {'name': 'A', 'lat': 48.843664, 'lon': 2.302672, 'type': 'small' },
     '008': {'name': 'B', 'lat': 50.575813, 'lon': 7.258148, 'type': 'medium'},
     '010': {'name': 'C', 'lat': 47.058420, 'lon': 15.437464,'type': 'big'}}

## IN THE ABOVE CASE. Duration: ~1 ms (milisecond)
tmp_list = []
for item_key, item_value in d.items() :
      'geometry' : Point(item_value['lon'], item_value['lat']),
      'id': item_key,
      'name': item_value ['name'],
      'type': item_value ['type']
gdf = gpd.GeoDataFrame(tmp_list)

## SOLUTION 1. Duration: ~2.3 ms, @gene's answer.
df = pd.DataFrame.from_dict(d, orient='index')
df["geometry"] = df.apply (lambda row: Point(row.lon,, axis=1)
gdf = gpd.GeoDataFrame(df, geometry=df.geometry)

## SOLUTION 2. Duration: ~2.5 ms
gdf = gpd.GeoDataFrame()    
gdf["id"]   = [k for k in d.keys()]
gdf["name"] = [d[k]["name"] for k in d.keys()]
gdf["type"] = [d[k]["type"] for k in d.keys()]
gdf["geometry"]  = [Point(d[k]["lon"], d[k]["lat"]) for k in d.keys()]    
gdf.set_index('id', inplace=True)

## SOLUTION 3. Duration: ~9.5 ms
gdf = gpd.GeoDataFrame(columns=["name", "type", "geometry"])
for k, v in d.items():
    gdf.loc[k] = (v["name"], v["type"], Point(v["lon"], v["lat"]))


# OUTPUT for the last solution
#     name    type                   geometry
# 007    A   small   POINT (2.30267 48.84366)
# 008    B  medium   POINT (7.25815 50.57581)
# 010    C     big  POINT (15.43746 47.05842)