@@ -340,6 +340,7 @@ def artist_story(
340340 last_decade : int | None ,
341341 work_title : str | None ,
342342 work_year : int | None ,
343+ score : float ,
343344) -> str :
344345 """Build a factual collection note without inventing biography."""
345346 country_phrase = (
@@ -360,12 +361,51 @@ def artist_story(
360361 work += f" ({ work_year } )"
361362 work += "."
362363 return (
363- f"In this dataset, { artist_name } is the most represented artist credited to { country_phrase } , "
364- f"with { n_works :,} credited works. MoMA's records place this artist mostly in { top_medium } , "
364+ f"In this dataset, { artist_name } has the highest collection prominence score for { country_phrase } "
365+ f"( { score :.1f } /100), with { n_works :,} credited works. MoMA's records place this artist mostly in { top_medium } , "
365366 f"with works appearing { span } .{ work } "
366367 )
367368
368369
370+ def prominence_table (group : pd .DataFrame ) -> pd .DataFrame :
371+ """Rank artists within one country using a transparent collection-based proxy."""
372+ stats = (
373+ group .groupby ("artist_id" )
374+ .agg (
375+ artist_name = ("artist_name" , "first" ),
376+ n_works = ("artwork_id" , "count" ),
377+ n_departments = ("department" , "nunique" ),
378+ n_mediums = ("medium_group" , "nunique" ),
379+ first_decade = ("decade" , "min" ),
380+ last_decade = ("decade" , "max" ),
381+ cataloged_share = ("cataloged" , lambda values : float ((values == "Y" ).mean ())),
382+ n_on_view = ("on_view" , lambda values : int (values .notna ().sum ())),
383+ has_wiki = ("has_wiki" , "max" ),
384+ has_ulan = ("has_ulan" , "max" ),
385+ )
386+ .reset_index ()
387+ )
388+ stats ["decade_span" ] = (stats ["last_decade" ] - stats ["first_decade" ]).fillna (0 ).clip (lower = 0 )
389+ max_works = max (1 , int (stats ["n_works" ].max ()))
390+ max_departments = max (1 , int (stats ["n_departments" ].max ()))
391+ max_mediums = max (1 , int (stats ["n_mediums" ].max ()))
392+ max_on_view = max (1 , int (stats ["n_on_view" ].max ()))
393+ stats ["prominence_score" ] = (
394+ 55 * stats ["n_works" ].map (lambda value : math .log1p (value ) / math .log1p (max_works ))
395+ + 12 * (stats ["n_departments" ] / max_departments )
396+ + 8 * (stats ["n_mediums" ] / max_mediums )
397+ + 8 * (stats ["decade_span" ].clip (upper = 160 ) / 160 )
398+ + 7 * stats ["cataloged_share" ]
399+ + 5 * stats ["has_wiki" ].astype (int )
400+ + 3 * stats ["has_ulan" ].astype (int )
401+ + 2 * (stats ["n_on_view" ] / max_on_view )
402+ ).round (2 )
403+ return stats .sort_values (
404+ ["prominence_score" , "n_works" , "artist_name" ],
405+ ascending = [False , False , True ],
406+ )
407+
408+
369409def load_lookup_files () -> tuple [dict [str , str ], dict [str , str ]]:
370410 with (DATA_DIR / "nationality_to_iso3.json" ).open ("r" , encoding = "utf-8" ) as handle :
371411 raw_nationality_to_iso = json .load (handle )
@@ -410,6 +450,8 @@ def build_credit_rows(artworks: pd.DataFrame, nationality_to_iso: dict[str, str]
410450 "classification" : clean_token (getattr (row , "Classification" )) or "Unknown" ,
411451 "medium" : clean_token (getattr (row , "Medium" )) or "Unknown" ,
412452 "medium_group" : getattr (row , "medium_group" ),
453+ "cataloged" : clean_token (getattr (row , "Cataloged" )),
454+ "on_view" : clean_token (getattr (row , "OnView" )),
413455 "nationality" : nationality ,
414456 "iso3" : iso3 ,
415457 "country_name" : ISO3_TO_COUNTRY .get (iso3 , iso3 ) if iso3 else None ,
@@ -456,6 +498,10 @@ def main() -> None:
456498
457499 credit_rows = build_credit_rows (artworks , nationality_to_iso , regions )
458500 credits = pd .DataFrame (credit_rows )
501+ wiki_lookup = artists_raw .set_index ("ConstituentID" )["Wiki QID" ].notna ().to_dict ()
502+ ulan_lookup = artists_raw .set_index ("ConstituentID" )["ULAN" ].notna ().to_dict ()
503+ credits ["has_wiki" ] = credits ["artist_id" ].map (wiki_lookup ).fillna (False )
504+ credits ["has_ulan" ] = credits ["artist_id" ].map (ulan_lookup ).fillna (False )
459505 n_total = len (artworks )
460506 n_credits = len (credits )
461507
@@ -514,7 +560,9 @@ def main() -> None:
514560 medium_counter = Counter (group ["medium_group" ])
515561 sorted_group = group .sort_values (["artist_name" , "title" , "year" ], na_position = "last" )
516562 sample = sorted_group .iloc [seeded_index (str (iso3 ), len (sorted_group ))]
517- featured_artist_id = int (group ["artist_id" ].value_counts ().sort_values (ascending = False ).index [0 ])
563+ ranked_artists = prominence_table (group )
564+ featured_rank = ranked_artists .iloc [0 ]
565+ featured_artist_id = int (featured_rank ["artist_id" ])
518566 featured_group = group [group ["artist_id" ] == featured_artist_id ].sort_values (["year" , "title" ], na_position = "last" )
519567 featured_sample = featured_group .iloc [0 ]
520568 featured_medium = Counter (featured_group ["medium_group" ]).most_common (1 )[0 ][0 ]
@@ -539,6 +587,17 @@ def main() -> None:
539587 "featured_artist_id" : featured_artist_id ,
540588 "featured_artist" : featured_sample ["artist_name" ],
541589 "featured_artist_n_works" : int (len (featured_group )),
590+ "featured_artist_score" : float (featured_rank ["prominence_score" ]),
591+ "featured_artist_score_method" : (
592+ "Collection prominence score: 55% log work count, 12% department breadth, "
593+ "8% medium breadth, 8% dated decade span, 7% cataloged share, "
594+ "5% Wiki QID, 3% ULAN, 2% currently-on-view records."
595+ ),
596+ "featured_artist_n_departments" : int (featured_rank ["n_departments" ]),
597+ "featured_artist_n_mediums" : int (featured_rank ["n_mediums" ]),
598+ "featured_artist_decade_span" : int (json_ready (featured_rank ["decade_span" ]) or 0 ),
599+ "featured_artist_has_wiki" : bool (featured_rank ["has_wiki" ]),
600+ "featured_artist_has_ulan" : bool (featured_rank ["has_ulan" ]),
542601 "featured_artist_lifespan" : lifespan (
543602 featured_sample ["year_birth" ],
544603 featured_sample ["year_death" ],
@@ -558,6 +617,7 @@ def main() -> None:
558617 featured_last ,
559618 featured_sample ["title" ],
560619 featured_work_year ,
620+ float (featured_rank ["prominence_score" ]),
561621 ),
562622 }
563623 )
0 commit comments