Module seesus.seesus

Identify 17 Sustainable Development Goals (SDGs) and their 169 targets in text, and classify into social, environmental, and economic sustainability.

Expand source code
"""Identify 17 Sustainable Development Goals (SDGs) and their 169 targets in text,
and classify into social, environmental, and economic sustainability."""

import regex as re

from seesus.SDG_keys import SDG_keys
from seesus.see_keys import see_keys
from seesus.SDG_desc import goal_desc, tar_desc

def id_sus(text):
    """
    Identify the UN Sustainable Development Goals (SDGs) and their associated targets in text.

    Parameters
    ----------
    text: str
        Text to be analyzed.
        It is recommended to input one sentence rather than a lengthy paragraph.

    Returns
    -------
    sus: bool
        Whether text aligns with sustainability as defined by the SDGs.
        True: text aligns with the SDGs.
        False: text does not align with the SDGs.
    sdgs: list
        Goal-level SDGs identified in text.
    targets: list
        SDG targets identified in text.
    matches: a list
        Match types, either "direct" (e.g., "no poverty" matches SDG1: No Poverty)
        or "indirect" (e.g., "no more starving" matches SDG2: Zero Hunger).

    Raises
    ------
    TypeError: if text is not a string.
    """
    if not isinstance(text, str): # check input data type
        raise TypeError("Input must be a string.")

    sdgs = []
    targets = []
    matches = []

    for item in SDG_keys:
        sdg_id = item["SDG_id"]
        sdg_keywords = item["SDG_keywords"]
        match_type = item["match_type"]
        if re.search(sdg_keywords, text, re.IGNORECASE):
            sdgs.append(sdg_id.split("_")[0])
            targets.append(sdg_id)
            matches.append(match_type)

    sdgs = list(set(sdgs)) # keep unique sdgs
    targets = list(set(targets))
    matches = list(set(matches))
    sus = bool(sdgs)

    return sus, sdgs, targets, matches

def cat_sus(target):
    """
    Categorize SDG targets into social, environmental, and economic sustainability.

    Parameters
    ----------
    target: list
        SDG targets.

    Returns
    -------
    see: dict
        A dictionary of boolean values with social, environmental, and economic sustainability
        as keys.
    """
    see = {"social_sustainability":0, "environmental_sustainability":0, "economic_sustainability":0}

    for item in see_keys:
        sdg_id, soc, env, econ = item[:4]
        for i in range(len(target)):
            if target[i] == sdg_id:
                see["social_sustainability"] += int(soc)
                see["environmental_sustainability"] += int(env)
                see["economic_sustainability"] += int(econ)

    see = {key: True if see[key] > 0 else False for key in see} # convert to boolean values

    return see

def label_sdg(sdg_id):
    """
    Label SDG id with SDG description.

    Parameters
    ----------
    sdg_id: list
        A list of SDG id.

    Returns
    -------
    sdg_desc: list
        SDG descriptions corresponding to the list of SDG id.
        Source: https://sdgs.un.org/goals
    """
    sdg_desc = []

    for item in goal_desc:
        goal_id, desc = item[:2]
        for i in range(len(sdg_id)):
            if sdg_id[i] == goal_id:
                sdg_desc.append(desc)

    return sdg_desc

def label_target(target_id):
    """
    Label target id with target description.

    Parameters
    ----------
    target_id: list
        A list of target id.

    Returns
    -------
    target_desc: list
        Target descriptions corresponding to the list of target id.
        Source: https://unstats.un.org/sdgs/indicators/indicators-list/
    """
    target_desc = []

    for item in tar_desc:
        tar_id, desc = item[:2]
        for i in range(len(target_id)):
            if target_id[i] == tar_id:
                target_desc.append(desc)

    return target_desc

class SeeSus():
    """
    A social, environmental, and economic sustainability classifier.

    Attributes
    ----------
    sus: bool
        Whether text aligns with sustainability as defined by the SDGs.
        True: text aligns with the SDGs.
        False: text does not align with the SDGs.
    sdg: list
        Goal-level SDGs identified in text.
    target: list
        SDG targets identified in text.
    match: list
        Match types, either "direct" (e.g., "no poverty" matches SDG1: No Poverty)
        or "indirect" (e.g., "no more starving" matches SDG2: Zero Hunger).
    sdg_desc: list
        SDG descriptions corresponding to the list of SDGs.
        Source: https://sdgs.un.org/goals
    target_desc: list
        Target descriptions corresponding to the list of SDG targets.
        Source: https://unstats.un.org/sdgs/indicators/indicators-list/
    see: dict
        A dictionary of boolean values with social, environmental, and economic sustainability
        as keys.
    """

    def __init__(self, text):
        """
        Parameters
        ----------
        text: str
            Text to be analyzed. It is recommended to input one sentence rather than
            a lengthy paragraph.
        """
        self.sus, self.sdg, self.target, self.match = id_sus(text)
        self.sdg_desc = label_sdg(self.sdg)
        self.target_desc = label_target(self.target)
        self.see = cat_sus(self.target)

    @staticmethod
    def show_syntax(sdg_id):
        """
        Print the regular expression match syntax of target-level SDGs.

        Parameters
        ----------
        sdg_id: str
            Target-level SDG id (e.g., "SDG1_1").

        Returns
        -------
        None

        Raises
        ------
        ValueError: if sdg_id is invalid.
        """
        ids = list({item["SDG_id"] for item in SDG_keys})
        if sdg_id not in ids: # check if sdg id is valid
            raise ValueError(f"Invalid input. Choose one in the list: {ids}")

        syntax = [d for d in SDG_keys if d["SDG_id"] == sdg_id]
        print(syntax)

    @staticmethod
    def edit_syntax(sdg_id, new_syntax, match_type="indirect"):
        """
        Edit the regular expression match syntax of target-level SDGs.

        Parameters
        ----------
        sdg_id: str
            Target level SDG id (e.g., "SDG1_1").
        new_syntax: str
            User defined matching syntax.
            More info on regular expressions: https://regex101.com/.
        match_type: str, optional
            The match type of syntax to be edited, either "direct" (e.g., "SDG 1")
            or "indirect" ("no more starving"). Default is "indirect".

        Returns
        -------
        None

        Raises
        ------
        ValueError: if sdg_id is invalid.
        ValueError: if match_type is invalid.
        """
        ids = list({item["SDG_id"] for item in SDG_keys})
        if sdg_id not in ids:  # check if sdg id is valid
            raise ValueError(f"Invalid input '{sdg_id}'. Use one in the list: {ids}.")
        if match_type not in ["direct", "indirect"]:  # check if match type is valid
            raise ValueError(
                f"Invalid input '{match_type}'. Use 'direct' or 'indirect'. Default is 'indirect'.")

        match = 0
        for item in SDG_keys:
            if item["SDG_id"] == sdg_id and item["match_type"] == match_type:
                match += 1
                item.update({"SDG_keywords": new_syntax})
        if match == 0: # when the direct/indirect match type does not exist
            SDG_keys.append({"SDG_id": sdg_id,
                             "SDG_keywords": new_syntax,
                             "match_type": match_type})

        print(f"The {match_type} match syntax of {sdg_id} has been updated.")

Functions

def cat_sus(target)

Categorize SDG targets into social, environmental, and economic sustainability.

Parameters

target : list
SDG targets.

Returns

see : dict
A dictionary of boolean values with social, environmental, and economic sustainability as keys.
Expand source code
def cat_sus(target):
    """
    Categorize SDG targets into social, environmental, and economic sustainability.

    Parameters
    ----------
    target: list
        SDG targets.

    Returns
    -------
    see: dict
        A dictionary of boolean values with social, environmental, and economic sustainability
        as keys.
    """
    see = {"social_sustainability":0, "environmental_sustainability":0, "economic_sustainability":0}

    for item in see_keys:
        sdg_id, soc, env, econ = item[:4]
        for i in range(len(target)):
            if target[i] == sdg_id:
                see["social_sustainability"] += int(soc)
                see["environmental_sustainability"] += int(env)
                see["economic_sustainability"] += int(econ)

    see = {key: True if see[key] > 0 else False for key in see} # convert to boolean values

    return see
def id_sus(text)

Identify the UN Sustainable Development Goals (SDGs) and their associated targets in text.

Parameters

text : str
Text to be analyzed. It is recommended to input one sentence rather than a lengthy paragraph.

Returns

sus : bool
Whether text aligns with sustainability as defined by the SDGs. True: text aligns with the SDGs. False: text does not align with the SDGs.
sdgs : list
Goal-level SDGs identified in text.
targets : list
SDG targets identified in text.
matches : a list
Match types, either "direct" (e.g., "no poverty" matches SDG1: No Poverty) or "indirect" (e.g., "no more starving" matches SDG2: Zero Hunger).

Raises

TypeError: if text is not a string.

Expand source code
def id_sus(text):
    """
    Identify the UN Sustainable Development Goals (SDGs) and their associated targets in text.

    Parameters
    ----------
    text: str
        Text to be analyzed.
        It is recommended to input one sentence rather than a lengthy paragraph.

    Returns
    -------
    sus: bool
        Whether text aligns with sustainability as defined by the SDGs.
        True: text aligns with the SDGs.
        False: text does not align with the SDGs.
    sdgs: list
        Goal-level SDGs identified in text.
    targets: list
        SDG targets identified in text.
    matches: a list
        Match types, either "direct" (e.g., "no poverty" matches SDG1: No Poverty)
        or "indirect" (e.g., "no more starving" matches SDG2: Zero Hunger).

    Raises
    ------
    TypeError: if text is not a string.
    """
    if not isinstance(text, str): # check input data type
        raise TypeError("Input must be a string.")

    sdgs = []
    targets = []
    matches = []

    for item in SDG_keys:
        sdg_id = item["SDG_id"]
        sdg_keywords = item["SDG_keywords"]
        match_type = item["match_type"]
        if re.search(sdg_keywords, text, re.IGNORECASE):
            sdgs.append(sdg_id.split("_")[0])
            targets.append(sdg_id)
            matches.append(match_type)

    sdgs = list(set(sdgs)) # keep unique sdgs
    targets = list(set(targets))
    matches = list(set(matches))
    sus = bool(sdgs)

    return sus, sdgs, targets, matches
def label_sdg(sdg_id)

Label SDG id with SDG description.

Parameters

sdg_id : list
A list of SDG id.

Returns

sdg_desc : list
SDG descriptions corresponding to the list of SDG id. Source: https://sdgs.un.org/goals
Expand source code
def label_sdg(sdg_id):
    """
    Label SDG id with SDG description.

    Parameters
    ----------
    sdg_id: list
        A list of SDG id.

    Returns
    -------
    sdg_desc: list
        SDG descriptions corresponding to the list of SDG id.
        Source: https://sdgs.un.org/goals
    """
    sdg_desc = []

    for item in goal_desc:
        goal_id, desc = item[:2]
        for i in range(len(sdg_id)):
            if sdg_id[i] == goal_id:
                sdg_desc.append(desc)

    return sdg_desc
def label_target(target_id)

Label target id with target description.

Parameters

target_id : list
A list of target id.

Returns

target_desc : list
Target descriptions corresponding to the list of target id. Source: https://unstats.un.org/sdgs/indicators/indicators-list/
Expand source code
def label_target(target_id):
    """
    Label target id with target description.

    Parameters
    ----------
    target_id: list
        A list of target id.

    Returns
    -------
    target_desc: list
        Target descriptions corresponding to the list of target id.
        Source: https://unstats.un.org/sdgs/indicators/indicators-list/
    """
    target_desc = []

    for item in tar_desc:
        tar_id, desc = item[:2]
        for i in range(len(target_id)):
            if target_id[i] == tar_id:
                target_desc.append(desc)

    return target_desc

Classes

class SeeSus (text)

A social, environmental, and economic sustainability classifier.

Attributes

sus : bool
Whether text aligns with sustainability as defined by the SDGs. True: text aligns with the SDGs. False: text does not align with the SDGs.
sdg : list
Goal-level SDGs identified in text.
target : list
SDG targets identified in text.
match : list
Match types, either "direct" (e.g., "no poverty" matches SDG1: No Poverty) or "indirect" (e.g., "no more starving" matches SDG2: Zero Hunger).
sdg_desc : list
SDG descriptions corresponding to the list of SDGs. Source: https://sdgs.un.org/goals
target_desc : list
Target descriptions corresponding to the list of SDG targets. Source: https://unstats.un.org/sdgs/indicators/indicators-list/
see : dict
A dictionary of boolean values with social, environmental, and economic sustainability as keys.

Parameters

text : str
Text to be analyzed. It is recommended to input one sentence rather than a lengthy paragraph.
Expand source code
class SeeSus():
    """
    A social, environmental, and economic sustainability classifier.

    Attributes
    ----------
    sus: bool
        Whether text aligns with sustainability as defined by the SDGs.
        True: text aligns with the SDGs.
        False: text does not align with the SDGs.
    sdg: list
        Goal-level SDGs identified in text.
    target: list
        SDG targets identified in text.
    match: list
        Match types, either "direct" (e.g., "no poverty" matches SDG1: No Poverty)
        or "indirect" (e.g., "no more starving" matches SDG2: Zero Hunger).
    sdg_desc: list
        SDG descriptions corresponding to the list of SDGs.
        Source: https://sdgs.un.org/goals
    target_desc: list
        Target descriptions corresponding to the list of SDG targets.
        Source: https://unstats.un.org/sdgs/indicators/indicators-list/
    see: dict
        A dictionary of boolean values with social, environmental, and economic sustainability
        as keys.
    """

    def __init__(self, text):
        """
        Parameters
        ----------
        text: str
            Text to be analyzed. It is recommended to input one sentence rather than
            a lengthy paragraph.
        """
        self.sus, self.sdg, self.target, self.match = id_sus(text)
        self.sdg_desc = label_sdg(self.sdg)
        self.target_desc = label_target(self.target)
        self.see = cat_sus(self.target)

    @staticmethod
    def show_syntax(sdg_id):
        """
        Print the regular expression match syntax of target-level SDGs.

        Parameters
        ----------
        sdg_id: str
            Target-level SDG id (e.g., "SDG1_1").

        Returns
        -------
        None

        Raises
        ------
        ValueError: if sdg_id is invalid.
        """
        ids = list({item["SDG_id"] for item in SDG_keys})
        if sdg_id not in ids: # check if sdg id is valid
            raise ValueError(f"Invalid input. Choose one in the list: {ids}")

        syntax = [d for d in SDG_keys if d["SDG_id"] == sdg_id]
        print(syntax)

    @staticmethod
    def edit_syntax(sdg_id, new_syntax, match_type="indirect"):
        """
        Edit the regular expression match syntax of target-level SDGs.

        Parameters
        ----------
        sdg_id: str
            Target level SDG id (e.g., "SDG1_1").
        new_syntax: str
            User defined matching syntax.
            More info on regular expressions: https://regex101.com/.
        match_type: str, optional
            The match type of syntax to be edited, either "direct" (e.g., "SDG 1")
            or "indirect" ("no more starving"). Default is "indirect".

        Returns
        -------
        None

        Raises
        ------
        ValueError: if sdg_id is invalid.
        ValueError: if match_type is invalid.
        """
        ids = list({item["SDG_id"] for item in SDG_keys})
        if sdg_id not in ids:  # check if sdg id is valid
            raise ValueError(f"Invalid input '{sdg_id}'. Use one in the list: {ids}.")
        if match_type not in ["direct", "indirect"]:  # check if match type is valid
            raise ValueError(
                f"Invalid input '{match_type}'. Use 'direct' or 'indirect'. Default is 'indirect'.")

        match = 0
        for item in SDG_keys:
            if item["SDG_id"] == sdg_id and item["match_type"] == match_type:
                match += 1
                item.update({"SDG_keywords": new_syntax})
        if match == 0: # when the direct/indirect match type does not exist
            SDG_keys.append({"SDG_id": sdg_id,
                             "SDG_keywords": new_syntax,
                             "match_type": match_type})

        print(f"The {match_type} match syntax of {sdg_id} has been updated.")

Static methods

def edit_syntax(sdg_id, new_syntax, match_type='indirect')

Edit the regular expression match syntax of target-level SDGs.

Parameters

sdg_id : str
Target level SDG id (e.g., "SDG1_1").
new_syntax : str
User defined matching syntax. More info on regular expressions: https://regex101.com/.
match_type : str, optional
The match type of syntax to be edited, either "direct" (e.g., "SDG 1") or "indirect" ("no more starving"). Default is "indirect".

Returns

None
 

Raises

ValueError: if sdg_id is invalid. ValueError: if match_type is invalid.

Expand source code
@staticmethod
def edit_syntax(sdg_id, new_syntax, match_type="indirect"):
    """
    Edit the regular expression match syntax of target-level SDGs.

    Parameters
    ----------
    sdg_id: str
        Target level SDG id (e.g., "SDG1_1").
    new_syntax: str
        User defined matching syntax.
        More info on regular expressions: https://regex101.com/.
    match_type: str, optional
        The match type of syntax to be edited, either "direct" (e.g., "SDG 1")
        or "indirect" ("no more starving"). Default is "indirect".

    Returns
    -------
    None

    Raises
    ------
    ValueError: if sdg_id is invalid.
    ValueError: if match_type is invalid.
    """
    ids = list({item["SDG_id"] for item in SDG_keys})
    if sdg_id not in ids:  # check if sdg id is valid
        raise ValueError(f"Invalid input '{sdg_id}'. Use one in the list: {ids}.")
    if match_type not in ["direct", "indirect"]:  # check if match type is valid
        raise ValueError(
            f"Invalid input '{match_type}'. Use 'direct' or 'indirect'. Default is 'indirect'.")

    match = 0
    for item in SDG_keys:
        if item["SDG_id"] == sdg_id and item["match_type"] == match_type:
            match += 1
            item.update({"SDG_keywords": new_syntax})
    if match == 0: # when the direct/indirect match type does not exist
        SDG_keys.append({"SDG_id": sdg_id,
                         "SDG_keywords": new_syntax,
                         "match_type": match_type})

    print(f"The {match_type} match syntax of {sdg_id} has been updated.")
def show_syntax(sdg_id)

Print the regular expression match syntax of target-level SDGs.

Parameters

sdg_id : str
Target-level SDG id (e.g., "SDG1_1").

Returns

None
 

Raises

ValueError: if sdg_id is invalid.

Expand source code
@staticmethod
def show_syntax(sdg_id):
    """
    Print the regular expression match syntax of target-level SDGs.

    Parameters
    ----------
    sdg_id: str
        Target-level SDG id (e.g., "SDG1_1").

    Returns
    -------
    None

    Raises
    ------
    ValueError: if sdg_id is invalid.
    """
    ids = list({item["SDG_id"] for item in SDG_keys})
    if sdg_id not in ids: # check if sdg id is valid
        raise ValueError(f"Invalid input. Choose one in the list: {ids}")

    syntax = [d for d in SDG_keys if d["SDG_id"] == sdg_id]
    print(syntax)