Thursday, January 21, 2021

Assign color to vector layer based on HTML Notation (HEX color) codes in attribute table

 Here, I have a polygon layer with 'color' attribute column which contains HEX color codes as seen below.


We want to assign each polygon to its attribute color value, for example: Delta = #6808C9.

This is close to 'Categorized Symbology', but the only difference is that the colors are from the attribute column. To do this, we have to edit the 'Fill Color' expression to read the color column.




This way, each polygon is given a HEX color code that corresponds to the value on the attribute column.




Happy Mapping!

Tuesday, January 12, 2021

Map two data frames base on common column

 The aim is to enrich a dataframe from a second dataframe. In other words, copy corresponding cell in a dataframe onto a second dataframe based on their common columns.

This is very common task that is difficult to explain! This works like a "vLookUp" function found in MS excel. Where we have two tables and we want to update the second table using correspond values based on column that relates them.

If the two tables have same name for the relating/common column, then the merge() function can be used like so: -

df2.merge(df1, on="common_column_name", how='inner')


On the other hand, if the relating/common column have varying column names and you don't want rename them. The below example would be more flexible:-

We create dictionary from columns in df2 and map it to df1



import pandas as pd
df1 = pd.DataFrame({'lkey': ['foo', 'bar', 'baz'],
                    'value0': [1, 2, 3]})

df2 = pd.DataFrame({'rkey': ['foo', 'bar', 'baz'],
                    'value1': [5, 6, 7],
                   'value2': [8, 9, 10]})

# This is a list of columns in: df2
s = ['rkey', 'value1', 'value2'] # Don't want to create it manually? then use: s = df2.columns.tolist()

# loop through all columns of df1 and map to df2
for column in s:
    # make a mapping dictionary from df...
    mydict = dict(zip(df2['rkey'], df2[column]))
    
    # create new column based on the map column and dictionary
    df1['new_'+column] = df1['lkey'].map(mydict)

df1


Here below is a real world example:-

Below are two tables with different attribute columns from countries in the world. The 'Country Name' and 'Country Code' columns are the same for both tables, so we need to merge them together.





Since, the two table have the same column names we can use this approach...

df1.merge(df2, on="Country Name", how='outer')

In case, the result isn't what you expected. Then play around with the parameters to get what you wanted.


Enjoy!

Tuesday, January 5, 2021

QGIS - Solve Launch alert on "python modules numpy and matplotlib both not installed"

When you start QGIS and got a screen start error that reads:-
The contour plugin is disabled as it requires python modules numpy and matplotlib which are not both installed.



This is custom error caused by a deprecated matplolib import command "from matplotlib.mlab import griddata". You can click on 'Ok' button to continue loading the QGIS software.

However, clicking on that button is somewhat annoying and you will definitely like to fix the error permanently.

The error comes from the 'contour' plugin that was installed in the plugins directory at: 
C:\Users\YourPcName\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\contour

Open the python file "ContourDialog.py" in your text editor. You would find and comment out the import statement "from matplotlib.mlab import griddata" and save the file.


This should fix the warning error massage from launching the software when you restart it.

The warning message box that pops up above is actually located in this same file somewhere below.



That is it!

Friday, January 1, 2021

Creating Zip file for items within multiple folders

 The script below will access all children folders within a parent directory then zip the contents and return back to the parent directory before moving to the next child folder.

The process continue until all children folders are processed.

# list of folders to zip their contents...
folders = glob.glob('*')

# Change dir to the first folder, zip its contents and return back to parent dir...
for folder in folders:
    # Change directory to folder in list of folders...
    os.chdir(folder)
    
    list_files = glob.glob('*')
    with zipfile.ZipFile(folder+'.zip', 'w') as zipF:
        for file in list_files:
            zipF.write(file, compress_type=zipfile.ZIP_DEFLATED)
    
    # Change directory back to main folder...
    os.chdir(r"C:\Users\Yusuf_08039508010\Documents\DandR")

print('Done...')


Note that the script uses the folder's name to name the resulting zip file as seen below.




That is it!