Skip to content
All library documents

Cleaning Crop Production Data and Estimating Missing Prices

Code quant-trading

Summary

This document describes a data preparation workflow for Malaysian crop production, harvested area, producer prices, land use, population, and GDP data over multiple years. It joins production with harvested area to calculate inverse yield, organizes crop records by year, and derives an economic lifespan adjustment for perennial crops. The resulting tables are combined into a dataset for further analysis.

The workflow filters crops with usable production, area, and price records, excludes a specified set, and fills selected missing prices using substitute price series or manually supplied estimates. It also repeats the latest available land observation for a later year. A commented section outlines synthetic control estimation of missing prices from other countries. The document gives implementation details but no validation results, error analysis, or evidence that the replacement prices are accurate. Several assumptions, including the chosen substitutes and lifespan parameters, would need checking before using the resulting data in research.

Key ideas

  • Production and harvested-area records are joined to derive an inverse-yield measure.
  • The workflow selects crops with matching production, area, and price data, then applies exclusions.
  • Missing crop prices are filled with substitute series or manually supplied values.
  • A commented synthetic-control approach proposes estimating missing prices from other countries.
  • The document does not assess imputation accuracy or downstream effects.

Tags

Full text
# cleanse data.py


```py

# coding: utf-8

# In[1]:


import os
os.chdir('H:/')
import pandas as pd
import numpy as np


# ### define functions

# In[2]:


#etl
def prepare(target_land,target_prod,target_prix):

    #land clean up
    target_land=target_land[['Year','Value']].copy()

    #prix clean up
    target_prix=target_prix[['Item','Year','Value']].copy()

    #create area and clean up
    target_area=target_prod[target_prod['Element']=='Area harvested'].copy()

    target_area=target_area[['Item','Year','Value','type','lifespan']].copy()

    #production clean up
    target_prod=target_prod[target_prod['Element']=='Production'].copy()

    target_prod=target_prod[['Item','Year','Value','class']].copy()

    #compute yield inverse and clean up
    target_yield_inverse=target_prod.merge(target_area,on=['Item','Year'],how='left')

    target_yield_inverse['Value']=np.divide(target_yield_inverse['Value_y'],target_yield_inverse['Value_x'])

    target_yield_inverse=target_yield_inverse[['Item', 'Year','Value','type', 'lifespan']]

    #sort by item and year
    for data in [target_prod,target_area,target_prix,target_yield_inverse]:
        data.sort_values(['Item','Year'],inplace=True)

    #concatenate
    global D
    D={}

    for currentyear in range(beginyear,endyear):   

        temp1=target_prod[target_prod['Year']==currentyear].merge(
        target_area[target_area['Year']==currentyear],on=['Item', 'Year'],how='outer')
        temp2=target_prix[target_prix['Year']==currentyear].merge(
        target_yield_inverse[target_yield_inverse['Year']==currentyear],on=['Item', 'Year'],how='outer')

        temp1.columns=temp1.columns.str.replace('Value_x','production')
        temp1.columns=temp1.columns.str.replace('Value_y','area')
        temp2.columns=temp2.columns.str.replace('Value_x','price')
        temp2.columns=temp2.columns.str.replace('Value_y','yield_i')

        data=temp1.merge(temp2,on=['Item', 'Year', 'type', 'lifespan'],how='outer')

        D[currentyear]=data                
    
    #compute eco lifespan for perennials
    for currentyear in range(beginyear,endyear):
        
        eco_lifespan=[default_discount for _ in range(len(D[currentyear]))]
        indices=D[currentyear]['lifespan'].dropna().index
        perennial=D[currentyear]['lifespan'].dropna().apply(lambda x:(x*eco_coeff-1)/(x*eco_coeff))

        for i in indices:
            eco_lifespan[i]=round(perennial.loc[i],4)

        D[currentyear]['eco lifespan']=eco_lifespan

    return D


# ### execution

# In[3]:


global beginyear,endyear
beginyear=2012
endyear=2019


# In[4]:


global eco_coeff,default_discount
eco_coeff=0.7
default_discount=0.8


# In[5]:


prod=pd.read_csv('Production_Crops_E_All_Data_(Normalized).csv',
                 encoding='latin-1')

prix=pd.read_csv('Prices_E_All_Data_(Normalized).csv',
                 encoding='latin-1')

land=pd.read_csv('Inputs_LandUse_E_All_Data_(Normalized).csv',
                 encoding='latin-1')

population=pd.read_csv('Population_E_All_Data_(Normalized).csv',
                      encoding='latin-1')

gdp=pd.read_csv('Macro-Statistics_Key_Indicators_E_All_Data_(Normalized).csv',
                      encoding='latin-1')


# In[6]:


os.chdir('H:/data')


# In[7]:


mapping=pd.read_csv('mapping.csv')


# In[8]:


#select malaysia from beginyear-endyear
malay_land=land[land['Year'].isin(range(beginyear,endyear))][land['Area']=='Malaysia'][land['Element'].isin(['Area'])][land['Item'].isin(['Cropland'])]

malay_prix=prix[prix['Year'].isin(range(beginyear,endyear))][prix['Area']=='Malaysia'][prix['Element']=='Producer Price (USD/tonne)'][prix['Months']=='Annual value']

malay_prod=prod[prod['Year'].isin(range(beginyear,endyear))][prod['Area']=='Malaysia'][prod['Element'].isin(['Area harvested','Production'])]

malay_pop=population[population['Element']=='Total Population - Both sexes'][population['Area']=='Malaysia'][population['Year']>=beginyear]

malay_gdp=gdp[gdp['Element']=='Value US$'][gdp['Item']=='Gross Domestic Product per capita'][gdp['Area']=='Malaysia'][gdp['Year'].isin(range(beginyear,endyear))]


# In[9]:


#exclude land usage<1%
exclude=[813,236,809,1717,
         512, 782, 656, 149, 667, 809,
         813, 689, 698, 702, 723, 217,
         226, 236, 242,463, 603, 619,
         1720, 1729, 1731, 1732, 1735,
         1738, 1753, 1804, 1841,1814]


# In[10]:


#find items without price
a=set(malay_prod['Item Code'][malay_prod['Element']=='Area harvested'])

b=set(malay_prod['Item Code'][malay_prod['Element']=='Production'])

c=set(malay_prix['Item Code'])

sans_prix=[i for i in a.intersection(b) if i not in c]

sans_prix=[i for i in sans_prix if i not in exclude]

print(sans_prix)


# In[11]:


#use austria oilseeds to replace
oilseeds_prix=prix[prix['Area']=='Austria'][prix['Element']=='Producer Price (USD/tonne)'][prix['Item Code']==339][prix['Year'].isin(range(beginyear,endyear))]


# In[12]:


#use avg of maize and rice to replace cereals
cereal_mean=malay_prix[malay_prix['Item'].isin(['Maize','Rice, paddy'])].groupby('Year').mean()['Value'].tolist()

cereal_prix=oilseeds_prix.copy()

cereal_prix['Value']=cereal_mean

cereal_prix['Item']='Cereals (Rice Milled Eqv)'

cereal_prix['Item Code']=1817


# In[13]:


#add missing
malay_prix=malay_prix.append(oilseeds_prix).append(cereal_prix)

malay_prix.reset_index(inplace=True,drop=True)


# In[14]:


#concat
malay_prod=malay_prod.merge(mapping,on=['Item Code', 'Item'],how='left')


# In[15]:


#find inner join of crops
a=set(malay_prod['Item Code'][malay_prod['Element']=='Area harvested'])

b=set(malay_prod['Item Code'][malay_prod['Element']=='Production'])

c=set(malay_prix['Item Code'])

target_crops=a.intersection(b).intersection(c)

targets=[i for i in target_crops if i not in exclude]


# In[16]:


#select crops
malay_prod=malay_prod[malay_prod['Item Code'].isin(targets)]
malay_prix=malay_prix[malay_prix['Item Code'].isin(targets)]


# In[17]:


#add 2018 land
land_2018=malay_land.iloc[-1:].copy()
land_2018.reset_index(inplace=True,drop=True)
land_2018.at[0,'Year']=2018
land_2018.at[0,'Year Code']=2018

malay_land=malay_land.append(land_2018)


# In[18]:


#export to csv
malay_land.to_csv('malay_land.csv',index=False)

malay_prod.to_csv('malay_prod.csv',index=False)

malay_prix.to_csv('malay_prix.csv',index=False)

malay_pop.to_csv('malay_pop.csv',index=False)

malay_gdp.to_csv('malay_gdp.csv',index=False)


# In[19]:


#concat
D=prepare(malay_land,malay_prod,malay_prix)

grand=pd.concat([D[i] for i in D])

grand.reset_index(inplace=True,drop=True)


# In[20]:


#create from synthetic control unit
malay_ginger=[1711.631924118213, 1918.0617150999785, 1926.352662122375, 1904.0526853161766]

malay_lettuce=[808.9104313117714, 809.2907573824596, 880.0718990821069, 801.194381901839]

malay_maize=[176.02653721679235, 181.61446377135653, 185.21444467527138]

malay_orange=[385.20868947337976, 303.6319254759596, 277.51641822220614, 376.92771860265077]

malay_sugarcane=[246.78089608441445]

malay_tobacco=[4345.956117624693,
 4091.368210599639,
 3638.8980233955585,
 3829.529414768218,
 3758.1754705530975,
 3889.6001454970665]


# In[21]:


#fill price
fillnull=dict(zip(grand['Item'][grand['price'].isnull()].unique(),
[malay_tobacco,malay_ginger,malay_lettuce,
 malay_orange,malay_maize,malay_sugarcane,]))

for i in fillnull:
    indices=grand[grand['Item']==i][grand['price'].isnull()].index.tolist()
    for j in indices:
        grand.at[j,'price']=fillnull[i][indices.index(j)]


# In[22]:


grand.to_csv('grand.csv',index=False)


# ### synthetic control unit

# In[23]:


# import statsmodels.api as sm

# #show missing items
# null=set(grand['Item'][grand['price'].isnull()])

# ss=grand[grand['Item'].isin(null)].sort_values(['Item','Year'])

# ss

# #split here

# #create synthetic control unit
# for ii in ss['Item'].unique():
    
#     print(ii)
    
#     #cleanse data
#     temp=prix[prix['Item']==ii][prix['Year'].isin(range(beginyear,endyear))][prix['Element']=='Producer Price (USD/tonne)'][prix['Months']=='Annual value']
#     temp=temp.pivot(index='Year',columns='Area',values='Value')
    
#     #delete null data
#     for i in temp:
#         if temp[i].isnull().any() and i!='Malaysia':
#             del temp[i]
    
#     #train
#     x=temp.loc[temp['Malaysia'].dropna().index]
#     del x['Malaysia']
#     y=temp['Malaysia'].dropna()
#     x.reset_index(inplace=True,drop=True)
#     y.reset_index(inplace=True,drop=True)

#     m=sm.OLS(y,x).fit()
    
#     #train result
#     print(m.predict(),y.tolist())
    
#     #test result
#     test=temp[temp['Malaysia'].isnull()]
#     test=test[[i for i in test.columns if i!='Malaysia']]
#     print(m.predict(test).tolist())


```

Shown in full with attribution under the source's licence. Licence: Apache-2.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.