View or edit on GitHub
This page is synchronized from trase/data/cote_divoire/trade/list_for_zdc_request.ipynb. Last modified on 2026-08-05 15:56 CEST by Harry Biddle.
Please view or edit the original file there; changes should be reflected here after a midnight build (CET time),
or manually triggering it with a GitHub action (link).
import boto3
from botocore.exceptions import NoCredentialsError, ClientError
def check_aws_access():
sts = boto3.client('sts')
try:
# Ask AWS "Who am I?"
identity = sts.get_caller_identity()
print("✅ Access Confirmed!")
print(f" Account: {identity['Account']}")
print(f" ARN: {identity['Arn']}")
# Optional: Check S3 specifically
s3 = boto3.client('s3')
s3.list_objects_v2(Bucket='trase-storage', MaxKeys=1)
print("✅ S3 Bucket 'trase-storage' is accessible.")
except NoCredentialsError:
print("❌ No AWS credentials found.")
except ClientError as e:
print(f"❌ Credentials found, but access denied: {e}")
except Exception as e:
print(f"❌ Error: {e}")
check_aws_access()
import pandas as pd
# Direct read from S3
path = 's3://trase-storage/cote_divoire/trade/cd/originals/CIV_2024_all_one_sheet.xlsx'
# Read the file
df = pd.read_excel(path)
df.replace(r'\n', '', regex=True, inplace=True)
# Check the data
display(df.head())
| YEAR | DATE | MONTH | RGITAR | SENS | IMMIMP | EXPORTER | SUPPLIER | GEN_CTY_DES_COD | DESTINATION | ... | TRANSPORT MODE | SH | COMMERCIAL PRODUCT DESC | NATURE_COLIS | UNIT | QUANTITY | FOB VALUE | CIF VALUE | NET WEIGHT | GROSS WEIGHT | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2024 | 17/01/2024 | 1 | E | EXPORT | 0815951Y | SOCIETE DE COMMERCIALISATION DE CAFE ET CACAO01 | AGRI COMMODITIES & FINANCE.FZ-LLC P.O. BOX 330578 | FR | France | ... | Transport maritime | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | VR | VR - Vrac solide, particules granuleuses | 1 | 355521478 | 355521478 | 200200 | 200200 |
| 1 | 2024 | 17/01/2024 | 1 | E | EXPORT | 1105355G | SUCDEN COTE D'IVOIRE15 BP 727 ABIDJAN (VILLE) 15 | SUCRES ET DENREES20/22 RUE DE LA VILLE L EVEQUE 7 | EE | ESTONIE | ... | Transport maritime | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | SA | SA - Sac ("sack") | 1155 | 115231310 | 115231310 | 75075 | 75849 |
| 2 | 2024 | 17/01/2024 | 1 | E | EXPORT | 0815951Y | SOCIETE DE COMMERCIALISATION DE CAFE ET CACAO01 B | COCOA TEAM 8 RUE SAINTE THERESE 33000 BORDEREAUX | DE | Allemagne | ... | Transport maritime | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | VR | VR - Vrac solide, particules granuleuses | 1 | 296701158 | 296701158 | 175175 | 175175 |
| 3 | 2024 | 09/01/2024 | 1 | E | EXPORT | 0918197U | CASB-SCOOPSBP 924 BOUAFLE (VILLE)BONON - | ECOM AGROTRADE .LTD 10TH FLOOR 55 OLD STREET TEL: | TR | Turquie | ... | Transport maritime | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | SA | SA - Sac ("sack") | 10780 | 1224562174 | 1224562174 | 700700 | 707924 |
| 4 | 2024 | 09/01/2024 | 1 | E | EXPORT | 0815951Y | SOCIETE DE COMMERCIALISATION DE CAFE ET CACAO01 B | JB FOODS GLOBAL PTE.LTD.80 ROBINSON ROAD #17-020 | MY | Malaisie | ... | Transport maritime | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | SA | SA - Sac ("sack") | 1155 | 132425911 | 132425911 | 75075 | 75849 |
5 rows × 23 columns
2021 Count: 691
2022 Count: 727
2023 Count: 798
2024 Count: 1038
df.columns
Index(['YEAR', 'DATE', 'MONTH', 'RGITAR', 'SENS', 'IMMIMP', 'EXPORTER ',
'SUPPLIER', 'GEN_CTY_DES_COD', 'DESTINATION', 'GEN_CTY_ORG', 'ORIGINE',
'CODE_MODE_TRANSP_FRONTIERE', 'TRANSPORT MODE', 'SH',
'COMMERCIAL PRODUCT DESC', 'NATURE_COLIS', 'UNIT', 'QUANTITY',
'FOB VALUE', 'CIF VALUE', 'NET WEIGHT', 'GROSS WEIGHT'],
dtype='object')
cols_to_fix = ['NET WEIGHT', 'GROSS WEIGHT', 'CIF VALUE']
for col in cols_to_fix:
df[col] = pd.to_numeric(df[col], errors='coerce').fillna(0)
df.SUPPLIER.unique()
array(['AGRI COMMODITIES & FINANCE.FZ-LLC P.O. BOX 330578',
'SUCRES ET DENREES20/22 RUE DE LA VILLE L EVEQUE 7',
'COCOA TEAM 8 RUE SAINTE THERESE 33000 BORDEREAUX', ...,
'PALMART GIDA KIMYA DIS TICARET LTD STI',
'PATISEN SA10 RUE MALAN BP 185 DAKAR / SENEGALDOS',
'CARGILL BV CARGILL COCOA & CHOCOLATE 1118 CZ SCHI'], dtype=object)
import pandas as pd
# --- EXPANDED MAPPING DICTIONARY ---
keyword_map = {
# --- MAJOR TRADERS ---
'CARGILL': 'CARGILL',
'OLAM': 'OLAM',
'TOUTON': 'TOUTON',
'TUTON': 'TOUTON',
'BARRY': 'BARRY CALLEBAUT',
'CALLEBAUT': 'BARRY CALLEBAUT',
'BC COCOA': 'BARRY CALLEBAUT',
'BC COCOA': 'BARRY CALLEBAUT', # Catches double spacing
'HARDTURMSTRASSE': 'BARRY CALLEBAUT', # Catches rows with only address
'ECOM': 'ECOM',
'THEOBROMA': 'THEOBROMA',
'THEOBOMA': 'THEOBROMA', # Typo in data
'GCB': 'GCB COCOA',
'WALTER MATTER': 'WALTER MATTER',
'WALTER MATTER': 'WALTER MATTER', # Double spacing
'COCOASOURCE': 'COCOASOURCE',
'COCOA SOURCE': 'COCOASOURCE',
'COCOA SUCRE': 'COCOASOURCE', # Likely related or similar naming convention
'ALBRECHT': 'ALBRECHT & DILL',
'ALBERCHT': 'ALBRECHT & DILL', # Typo in data
# --- SUCDEN VARIATIONS ---
'SUCDEN': 'SUCDEN',
'SUCRES': 'SUCDEN',
'DENREE': 'SUCDEN',
'DENRÉES': 'SUCDEN',
# --- SPECIFIC ENTITIES FROM YOUR LIST ---
'HUYSER': 'HUYSER MÖLLER',
'MARKEY': 'R. MARKEY & SONS',
'ONEM GIDA': 'ONEM GIDA',
'LOGIKA': 'LOGIKA',
'MOI INTERNATIONAL': 'MOI INTERNATIONAL',
'COTTERELL': 'H.D. COTTERELL',
'FUCHS': 'FUCHS & HOFFMANN',
'FACTA': 'FACTA INTERNATIONAL',
'FACTS INTERNATIONAL': 'FACTA INTERNATIONAL',
'PACTA': 'FACTA INTERNATIONAL', # Typo in data
'ASIA COCOA INDONESIA': 'ASIA COCOA INDONESIA',
'ALTINMARKA': 'ALTINMARKA',
'CACAO LATITUDES': 'CACAO LATITUDES',
'AGROINDUSTRIAS': 'AGROINDUSTRIAS UNIDAS',
'IVCOM': 'IVCOM',
'ECORIGINE': 'ECORIGINE',
'CEMOI': 'CEMOI',
'ENTREP COOPERA': 'ENTREP COOPERA',
'AFRICA SOURCING': 'AFRICA SOURCING',
'TRANSCAO': 'TRANSCAO',
'OUTSPAN': 'OUTSPAN',
'ETHIQUABLE': 'ETHIQUABLE',
'COMERCIALIZADORA': 'COMERCIALIZADORA ECO CACAO',
'COMMERCIALIZADORA': 'COMERCIALIZADORA ECO CACAO', # Typo/Spelling
'AGROFOREST': 'AGROFOREST',
'PPC GRYF': 'PPC GRYF',
'ULKER': 'ULKER',
'NINH THUAN': 'NINH THUAN NITAGREX',
'CEVA': 'CEVA LOGISTICS',
'TERRACORE': 'TERRACORE',
'DEPENDABLE': 'DEPENDABLE DISTRIBUTION',
'DOMORI': 'DOMORI',
'GUAN CHONG': 'GUAN CHONG',
'ALCAO': 'ALCAO',
'DP.COCO': 'DP COCO',
'GEZAIRI': 'GEZAIRI TRANS',
'JS COCOA': 'JS COCOA',
'JS. COCOA': 'JS COCOA',
'JS.COCOA': 'JS COCOA',
'BALTIC': 'BALTIC COCOA', # Broadened to catch "U A B BALTIC"
'SINTAG': 'SINTAG',
'PACHE': 'F. PACHE',
'PANAMIR': 'PANAMIR',
'DE MAN': 'DE MAN MET SMAAK',
'ELSHAMADAN': 'EL SHAMADAN',
'EL SHAMADAN': 'EL SHAMADAN',
'ANHUI': 'ANHUI IMPORT',
'DKS': 'DKS COCOA',
'LIFE BV': 'LIFE BV',
'LIFE B.V': 'LIFE BV',
'INDCRE': 'INDCRESA',
'IBERCOMMODITIES': 'IBERCOMMODITIES',
'IBER COMMODITIES': 'IBERCOMMODITIES',
'IBERCOMMODITES': 'IBERCOMMODITIES', # Typo in data
'AGRI MANGEMENT': 'AGRI COMMODITIES',
'PT ANEKA': 'PT ANEKA',
'INDUSTRIAL FOOD': 'INDUSTRIAL FOOD COMPANY',
'LACASA': 'LACASA',
'EUROPRALINE': 'EUROPRALINE',
'EUROPROLINE': 'EUROPRALINE',
'ARGINI': 'ARGINI TRADING',
'CENTRUM': 'CENTRUM INFORMACJI',
'ALINDA': 'ALINDA-VELCO',
'PASTOR': 'PASTOR SA',
'GIBSON': 'GIBSON LLC',
'LACTAVIT': 'LACTAVIT',
'GARLAND': 'GARLAND',
'YIOTIS': 'YIOTIS',
'MULTITRADE': 'MULTITRADE SPAIN',
'MULTLITRADE': 'MULTITRADE SPAIN',
'MULTIRADE': 'MULTITRADE SPAIN',
'AL ZAYTUNA': 'AL ZAYTUNA',
'S.GROUP': 'S GROUP SL',
'S GROUP': 'S GROUP SL',
'INDUSTRIA CAPIXABA': 'INDUSTRIA CAPIXABA',
'C&R': 'C&R COMMODITIES',
'C & R': 'C&R COMMODITIES',
'TCC TURIZM': 'TCC TURIZM',
'CAMPAGNOLI': 'CAMPAGNOLI & RODRIGUEZ',
'PLOT ENTERPRISE': 'PLOT ENTERPRISE',
'MIESZKAO': 'MIESZKO',
'MIESZKO': 'MIESZKO',
'MONPIT': 'MONPIT',
'LA CREMA': 'LA CREMA',
'KWIK HOLLAND': 'KWIK HOLLAND',
'INGREDIOR': 'INGREDIOR',
'VICOCOA': 'VICOCOA',
'TRADING & SERVICES': 'TRADING & SERVICES',
'ATC AFRICA': 'ATC AFRICA',
'CACAO LIFE': 'CACAO LIFE',
'IP RUMYANTSE': 'IP RUMYANTSE',
'SEN ALIM': 'SEN ALIM',
'LE FOUR': 'LE FOUR DU KHALIFE',
'CRISA': 'CRISA',
'ALBACORA': 'ALBACORA',
'AMAR TRADING': 'AMAR TRADING',
'LEBANESE ROASTERY': 'LEBANESE ROASTERY',
'CANADA INC': 'CANADA INC (11601148)',
'SOFAPRAL': 'SOFAPRAL',
'NEW FOODS': 'NEW FOODS',
'HABIBO': 'HABIBO',
'IMCD': 'IMCD',
'CHRISTINE GLOUX': 'CHRISTINE GLOUX',
'CARRE MARCHE': 'CARRE MARCHE',
'PALMART': 'PALMART',
'SENALIA': 'SENALIA',
'ROMSHIP': 'ROMSHIP',
'SOBCO': 'SOBCO',
'IVOIRE CACAO': 'IVOIRE CACAO',
'KANSO': 'KANSO KASSEM',
'SOCIETE AGRICOLE': 'SACC',
'ECAKOOG': 'ECAKOOG',
'IGI SPA': 'IGI SPA',
# --- ORIGINAL LIST (RETAINED) ---
'NEDERLAND': 'NEDERLAND SA',
'IBERCACAO': 'IBERCACAO',
'AGROFORCE': 'AGROFORCE',
'ASCOT': 'ASCOT AMSTERDAM',
'ACT INTER': 'ACT INTERNATIONAL',
'AFRICAO': 'AFRICAO',
'AGRI COMMODITIES': 'AGRI COMMODITIES',
'MONER': 'MONER COCOA',
'TAN MONDIAL': 'TAN MONDIAL',
'JB FOOD': 'JB FOODS',
'JB COCOA': 'JB FOODS',
'KSW': 'KSW GLOBAL',
'ARASCO': 'ARASCO',
'ARSCO': 'ARASCO', # Typo in data
'COMOD': 'COMOD',
'VIGOLIN': 'VIGOLIN',
'TRILINI': 'TRILINI',
'TEPCO': 'TEPCO',
'MISCAL': 'MISCAL',
'COCOA TEAM': 'COCOA TEAM',
'CHOCOLATES DEL NORTE': 'CHOCOLATES DEL NORTE',
'DEL NORTE': 'CHOCOLATES DEL NORTE',
'UCOM': 'UCOM',
'ANCILE': 'ANCILE',
'QUAST': 'QUAST & CONS',
'LOTTE': 'LOTTE',
'YIWU': 'YIWU XINDU',
'SENICO': 'SENICO',
'PATISEN': 'PATISEN',
'KATOEN': 'KATOEN NATIE',
'BOLLORE': 'BOLLORE',
'CWT': 'CWT COMMODITIES',
'FERRERO': 'FERRERO',
'NESTLE': 'NESTLE',
'MARS': 'MARS',
'MITSUI': 'MITSUI'
}
def clean_company_name(text):
if pd.isna(text):
return text
# Convert to upper case for matching
text_upper = str(text).upper()
# Check for keywords
for keyword, standard_name in keyword_map.items():
if keyword in text_upper:
return standard_name
# Return original text if no match found
return text
# Apply the cleaning
df['SUPPLIER_CLEAN'] = df['SUPPLIER'].apply(clean_company_name)
# --- VALIDATION ---
print("--- Top 40 Suppliers (Cleaned) ---")
print(df['SUPPLIER_CLEAN'].value_counts().head(40))
# OPTIONAL: Check what is left
clean_names = set(keyword_map.values())
uncrunchable = df[
(df['SUPPLIER_CLEAN'].str.len() > 20) &
(~df['SUPPLIER_CLEAN'].isin(clean_names))
]['SUPPLIER_CLEAN'].unique()
print("\n--- Remaining Messy Rows ---")
print(uncrunchable)
--- Top 40 Suppliers (Cleaned) ---
CARGILL 2616
BARRY CALLEBAUT 2279
OLAM 2138
SUCDEN 938
ECOM 730
THEOBROMA 658
GCB COCOA 621
TOUTON 426
ACT INTERNATIONAL 299
COMOD 252
COCOASOURCE 193
AFRICAO 182
AGRI COMMODITIES 176
CEMOI 157
UCOM 156
MONER COCOA 136
TAN MONDIAL 100
JB FOODS 85
KSW GLOBAL 79
DKS COCOA 77
IBERCACAO 69
ALBRECHT & DILL 65
NEDERLAND SA 63
VIGOLIN 44
YIWU XINDU 39
INDCRESA 38
FACTA INTERNATIONAL 34
AGROFORCE 33
ARASCO 33
WALTER MATTER 29
LOGIKA 28
BALTIC COCOA 28
PPC GRYF 25
ASCOT AMSTERDAM 24
TRILINI 24
COCOA TEAM 22
CHOCOLATES DEL NORTE 22
KATOEN NATIE 19
ROMSHIP 19
QUAST & CONS 16
Name: SUPPLIER_CLEAN, dtype: int64
--- Remaining Messy Rows ---
['DIVERS DESTINATAIRES' 'STE COOP UN.PROD AGR DJAK BP 1205SAN-PEDROCITE-'
'STE COOP AGRI DE TOUIH BP 142 SAN-PEDRO (VILLE)T'
'STE COOP AGRI DE TOUIHBP 142 SAN-PEDRO (VILLE)TO'
'SOCIETE COOP AGR EXPL DEP DALOA5(SCAEDA)BP 17 DA'
'STE COOP DESI-CAO NIAPIDOUBP SASSANDRA (VILLE)NI'
'STE COOP AGRI DE TOUIH BP 142 SAN -PEDRO (VILLE)'
'STE COOP AGRICUL DE GAGNY CARBP SAN-PEDROGAGNY C'
'COMMODITY CTRA DE LA VILA 48 088480 BARCELONE SPA'
'AGRI MANAGEMENT FZ-LLCRIB 211B,RAK INSURRANCE BUI'
'I.G.I SPA.ZONA INDUSTRIELE PALOMONTEITALIE']
display(df['SUPPLIER_CLEAN'].value_counts().tail(150))
NEDERLAND SA 63
VIGOLIN 44
YIWU XINDU 39
INDCRESA 38
FACTA INTERNATIONAL 34
..
TME24A0618 1
STE COOP AGRICUL DE GAGNY CARBP SAN-PEDROGAGNY C 1
SANSTME24S1124 1
TME24A0501 1
PALMART 1
Name: SUPPLIER_CLEAN, Length: 150, dtype: int64
len(df['SUPPLIER_CLEAN'].unique())
172
df['SUPPLIER_CLEAN']
0 AGRI COMMODITIES
1 SUCDEN
2 COCOA TEAM
3 ECOM
4 JB FOODS
...
13483 CARGILL
13484 CARGILL
13485 CARGILL
13486 CARGILL
13487 CARGILL
Name: SUPPLIER_CLEAN, Length: 13488, dtype: object
import pandas as pd
def get_top_contributors(df, entity_col, metric_col, threshold=0.97):
"""
Returns the dataframe of entities that account for the top 90%
of the given metric.
"""
# 1. Group and sum
grouped = df.groupby(entity_col, as_index=False)[metric_col].sum()
# 2. Sort descending
grouped = grouped.sort_values(by=metric_col, ascending=False).reset_index(drop=True)
# 3. Cumulative percentage
total_volume = grouped[metric_col].sum()
grouped['cumulative_share'] = grouped[metric_col].cumsum() / total_volume
# 4. Filter top 90%
cutoff_mask = grouped['cumulative_share'] >= threshold
if cutoff_mask.any():
cutoff_index = grouped[cutoff_mask].index[0]
top_entities = grouped.loc[:cutoff_index].copy()
else:
top_entities = grouped.copy()
return top_entities
# --- CONFIGURATION ---
metrics = ['NET WEIGHT', 'CIF VALUE']
# --- EXECUTION ---
metric_dfs = {}
for metric in metrics:
# We specifically ask for 'SUPPLIER' here
metric_dfs[metric] = get_top_contributors(df, 'SUPPLIER_CLEAN', metric)
# --- ACCESS RESULTS ---
df_net = metric_dfs['NET WEIGHT']
df_cif = metric_dfs['CIF VALUE']
# --- COMPARISON LOGIC ---
print("\n" + "="*50)
print("COMPARISON: Overlap between Net Weight and CIF Value")
print("="*50)
# FIX: We must select the specific column ['SUPPLIER'] before making a set
base_companies = set(df_net['SUPPLIER_CLEAN'])
comp_companies = set(df_cif['SUPPLIER_CLEAN'])
# Find overlap
in_both = base_companies.intersection(comp_companies)
only_in_net = base_companies - comp_companies
only_in_cif = comp_companies - base_companies
print(f"Total top Suppliers by NET WEIGHT: {len(base_companies)}")
print(f"Total top Suppliers by CIF VALUE: {len(comp_companies)}")
print(f"Suppliers in BOTH lists: {len(in_both)}")
print("-" * 30)
if len(only_in_net) > 0:
print(f"Suppliers ONLY in Net Weight (Top 5): {list(only_in_net)[:5]}")
else:
print("All Net Weight suppliers are also in CIF list.")
if len(only_in_cif) > 0:
print(f"Suppliers ONLY in CIF Value (Top 5): {list(only_in_cif)[:5]}")
else:
print("All CIF suppliers are also in Net Weight list.")
==================================================
COMPARISON: Overlap between Net Weight and CIF Value
==================================================
Total top Suppliers by NET WEIGHT: 37
Total top Suppliers by CIF VALUE: 33
Suppliers in BOTH lists: 31
------------------------------
Suppliers ONLY in Net Weight (Top 5): ['DKS COCOA', 'TRILINI', 'INDCRESA', 'ONEM GIDA', 'QUAST & CONS']
Suppliers ONLY in CIF Value (Top 5): ['IBERCACAO', 'ROMSHIP']
base_companies
{'ACT INTERNATIONAL',
'AFRICAO',
'AGRI COMMODITIES',
'AGROFORCE',
'ALBRECHT & DILL',
'ANCILE',
'ARASCO',
'ASCOT AMSTERDAM',
'BARRY CALLEBAUT',
'CARGILL',
'CEMOI',
'COCOA TEAM',
'COCOASOURCE',
'COMOD',
'DKS COCOA',
'ECOM',
'FACTA INTERNATIONAL',
'FUCHS & HOFFMANN',
'GCB COCOA',
'INDCRESA',
'JB FOODS',
'KATOEN NATIE',
'KSW GLOBAL',
'LOGIKA',
'MONER COCOA',
'NEDERLAND SA',
'OLAM',
'ONEM GIDA',
'QUAST & CONS',
'SUCDEN',
'TAN MONDIAL',
'THEOBROMA',
'TOUTON',
'TRILINI',
'UCOM',
'ULKER',
'WALTER MATTER'}
df[df.SUPPLIER_CLEAN=='UCOM']
| YEAR | DATE | MONTH | RGITAR | SENS | IMMIMP | EXPORTER | SUPPLIER | GEN_CTY_DES_COD | DESTINATION | ... | SH | COMMERCIAL PRODUCT DESC | NATURE_COLIS | UNIT | QUANTITY | FOB VALUE | CIF VALUE | NET WEIGHT | GROSS WEIGHT | SUPPLIER_CLEAN | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 452 | 2024 | 18/01/2024 | 1 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL,26-28, RUE DANIELLE CASANOVA 75002 PARI | ID | Indonesie | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 770 | 73538683 | 76824372 | 50050 | 50566 | UCOM |
| 694 | 2024 | 25/01/2024 | 1 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL, 26-28 ,RUE DANIELLE CASANOVA 75002 PA | ID | Indonesie | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 1540 | 153647432 | 153647432 | 100100 | 101132 | UCOM |
| 772 | 2024 | 25/01/2024 | 1 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL, 26-28 ,RUE DANIELLE CASANOVA 75002 PA | ID | Indonesie | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 8470 | 845060876 | 845060876 | 550550 | 556226 | UCOM |
| 811 | 2024 | 26/01/2024 | 1 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL 26-28, RUE DANIELLE CASANOVA 75002 PARI | ID | Indonesie | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 770 | 76823716 | 76823716 | 50050 | 50566 | UCOM |
| 864 | 2024 | 2024-02-08 00:00:00 | 2 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL, 26-28, RUE DANIELLE CASANOVA 75002 PAR | MY | Malaisie | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 3850 | 398161963 | 398161963 | 250250 | 252830 | UCOM |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4821 | 2024 | 2024-12-05 00:00:00 | 12 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL, 26-28, RUE DANIELLE CASANOVA75002 PARI | BR | Bresil | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 7700 | 2410754800 | 2410754800 | 500500 | 505660 | UCOM |
| 4865 | 2024 | 2024-12-05 00:00:00 | 12 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL, 26-28, RUE DANIELLE CASANOVA75002 PARI | BR | Bresil | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 2310 | 723226702 | 723226702 | 150150 | 151698 | UCOM |
| 4916 | 2024 | 2024-12-27 00:00:00 | 12 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL, 26-28, RUE DANIELLE CASANOVA75002 PARI | CA | CANADA | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 1925 | 711996062 | 711996062 | 125125 | 126415 | UCOM |
| 5057 | 2024 | 2024-12-13 00:00:00 | 12 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL, 26-28, RUE DANIELLE CASANOVA75002 PARI | CA | CANADA | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 385 | 142399081 | 142399081 | 25025 | 25283 | UCOM |
| 5262 | 2024 | 2024-12-05 00:00:00 | 12 | E | EXPORT | 4263085W | CYRIAN INTERNATIONAL01 BP 2734 ABIDJAN (VILLE) 01 | UCOM SARL, 26-28, RUE DANIELLE CASANOVA75002 PARI | BR | Bresil | ... | 1801001200 | 1801001200 - -- Cacao brut en fèves, qualité c... | JT | JT - Sac en jute | 5390 | 1687528097 | 1687528097 | 350350 | 353962 | UCOM |
156 rows × 24 columns
Using cocoa bean equivalent factors
import pandas as pd
df_2023 = pd.read_csv("/Users/niamhfrench/Library/CloudStorage/OneDrive-SEI/Documents/TRASE/trase/data/cote_divoire/trade/civ_cocoa_2023_trader_groups_cleaned.csv")
df_2024 = pd.read_csv("/Users/niamhfrench/Library/CloudStorage/OneDrive-SEI/Documents/TRASE/trase/data/cote_divoire/trade/civ_cocoa_2024_trader_groups_cleaned.csv")
# 1. Setup the dataframe (assuming your dataframe is named 'df')
# We drop the NaN row at the end to ensure clean calculations
df = df_2023.dropna(subset=['TRADER_BEQ_VOLUME_EXPORTED'])
# 2. Sort by volume descending (Crucial step for Pareto/cumulative analysis)
df_sorted = df.sort_values(by='TRADER_BEQ_VOLUME_EXPORTED', ascending=False).copy()
# 3. Calculate the cumulative percentage
total_volume = df_sorted['TRADER_BEQ_VOLUME_EXPORTED'].sum()
df_sorted['cumulative_share'] = df_sorted['TRADER_BEQ_VOLUME_EXPORTED'].cumsum() / total_volume
# 4. Filter to keep rows that make up the top 90%
# We use shift(1) < 0.9 to ensure we include the specific trader that crosses
# the 90% threshold, ensuring we cover *at least* 90% of the volume.
top_90_df = df_sorted[df_sorted['cumulative_share'].shift(1, fill_value=0) < 0.91]
# Optional: View the result
print(top_90_df[['EXPORTER_GROUP_CLEAN', 'TRADER_BEQ_VOLUME_EXPORTED', 'cumulative_share']])
# Get just the list of names
top_90_names = top_90_df['EXPORTER_GROUP_CLEAN'].tolist()
print(f"\nNumber of exporters in top 90%: {len(top_90_names)}")
EXPORTER_GROUP_CLEAN TRADER_BEQ_VOLUME_EXPORTED cumulative_share
0 BARRY CALLEBAUT 2.669343e+08 0.151225
1 CARGILL 2.535920e+08 0.294892
2 OLAM 2.263913e+08 0.423148
3 ECOM 1.854078e+08 0.528187
4 TOUTON 1.604826e+08 0.619104
5 SUCDEN 1.344604e+08 0.695280
6 ETC GROUP 7.167884e+07 0.735888
7 SOCIETE AWAHUS SERVICES 6.819157e+07 0.774520
8 GUAN CHONG COCOA 5.188888e+07 0.803916
9 CEMOI 3.870722e+07 0.825845
10 S3C 3.842800e+07 0.847616
11 TANMONDIAL 3.573570e+07 0.867861
12 COCOASOURCE 2.764042e+07 0.883520
13 SACC 2.137789e+07 0.895631
14 SCAT (COOPERATIVE) 2.037372e+07 0.907173
15 FILDISI 1.641655e+07 0.916474
Number of exporters in top 90%: 16
# 1. Setup the dataframe (assuming your dataframe is named 'df')
# We drop the NaN row at the end to ensure clean calculations
df = df_2024.dropna(subset=['TRADER_BEQ_VOLUME_EXPORTED'])
# 2. Sort by volume descending (Crucial step for Pareto/cumulative analysis)
df_sorted = df.sort_values(by='TRADER_BEQ_VOLUME_EXPORTED', ascending=False).copy()
# 3. Calculate the cumulative percentage
total_volume = df_sorted['TRADER_BEQ_VOLUME_EXPORTED'].sum()
df_sorted['cumulative_share'] = df_sorted['TRADER_BEQ_VOLUME_EXPORTED'].cumsum() / total_volume
# 4. Filter to keep rows that make up the top 90%
# We use shift(1) < 0.9 to ensure we include the specific trader that crosses
# the 90% threshold, ensuring we cover *at least* 90% of the volume.
top_90_df = df_sorted[df_sorted['cumulative_share'].shift(1, fill_value=0) < 0.91]
# Optional: View the result
print(top_90_df[['EXPORTER_GROUP_CLEAN', 'TRADER_BEQ_VOLUME_EXPORTED', 'cumulative_share']])
# Get just the list of names
top_90_names = top_90_df['EXPORTER_GROUP_CLEAN'].tolist()
print(f"\nNumber of exporters in top 90%: {len(top_90_names)}")
EXPORTER_GROUP_CLEAN TRADER_BEQ_VOLUME_EXPORTED cumulative_share
0 BARRY CALLEBAUT 2.669343e+08 0.151225
1 CARGILL 2.535920e+08 0.294892
2 OLAM 2.263913e+08 0.423148
3 ECOM 1.854078e+08 0.528187
4 TOUTON 1.604826e+08 0.619104
5 SUCDEN 1.344604e+08 0.695280
6 ETC GROUP 7.167884e+07 0.735888
7 SOCIETE AWAHUS SERVICES 6.819157e+07 0.774520
8 GUAN CHONG COCOA 5.188888e+07 0.803916
9 CEMOI 3.870722e+07 0.825845
10 S3C 3.842800e+07 0.847616
11 TANMONDIAL 3.573570e+07 0.867861
12 COCOASOURCE 2.764042e+07 0.883520
13 SACC 2.137789e+07 0.895631
14 SCAT (COOPERATIVE) 2.037372e+07 0.907173
15 FILDISI 1.641655e+07 0.916474
Number of exporters in top 90%: 16