<jupyter_start><jupyter_text>Introduction to scatter plotsThis lesson will introduce scatter plots and how to make them in several different ways. We will start by importing the ANSS earthquake catalog which you can download [here](http://www.ncedc.org/anss/catalog-search.html). For your convenience this file is also provided in the data folder.The catalog provided is for magnitude >= 5 events occurring between 1997 and 2009 worldwide. For easy import, it is best to download a CSV version.<jupyter_code>%matplotlib inline
import pandas as pd
# read the data, set space delimiter, and get rid of the dash line in 1st line after header
df = pd.read_csv('data/anss.csv', delim_whitespace=True, skiprows=[1])
df.head()<jupyter_output><empty_output><jupyter_text>What are these columns?Some are self explanatory but some are not:* MagT - magnitude type, the way the magnitude was calculated* Nst - the number of stations used to locate the earthquake* Gap - azimuthal gap of stations used to locate the earthquake* RMS - root mean square error for the location* SRC - network organization that reported the event* EventID - ID number assigned to the event<jupyter_code>df.describe()<jupyter_output><empty_output><jupyter_text>Scatter plots are used to look at how two variables compare. For example, does the Magnitude of the earthquake correlate in some way to the number of stations used to locate it?<jupyter_code>df.plot(kind='scatter', x='Mag', y='Nst')<jupyter_output><empty_output><jupyter_text>We can clean this plot up a lot though. Lets start by looking at the machinery that creates it.<jupyter_code>import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, figsize=(8,5))

df.plot(ax=ax, kind='scatter', x='Mag', y='Nst', alpha=0.15, edgecolor='None'
       ,color='violet')

ax.set_ylim(0, 1000)
ax.set_xlim(4.5, 10)
ax.grid(True)
ax.set_title('Does the number of stations change for the magnitude?')

ax.set_ylabel('Number of Stations')
ax.set_xlabel('Magnitude')<jupyter_output><empty_output><jupyter_text>Gutenberg-Richter plots In seismology, the Gutenberg–Richter law expresses the relationship between the magnitude and total number of earthquakes (that is the distribution) in any given region and time period of at least that magnitude.$log_{10}N = a -bM$or$N = 10^{a-bM}$Where:* $N$  is the number of events having a magnitude, $\geq M$ * $a$  and $b$  are constants.It is assumed to be poissonian.To create the Gutenburg-Richter distribution of the earthquake magnitudes from the ANSS catalog, we are going to use numpy.<jupyter_code>import numpy as np
df.Mag.values.round(1)
hist, edges = np.histogram(a=df.Mag.values.round(1), bins=101, range=(0,10))
chist = np.cumsum(hist[::-1])[::-1]
edges
hist
fig, ax = plt.subplots()

ax.plot(edges[:-1], hist, marker='s', color='None', linestyle='')
ax.plot(edges[:-1], chist, marker='^', color='red', linestyle='')
ax.set_yscale('log')
ax.set_ylabel('N')
ax.set_xlabel('Magnitude')
ax.set_title('Gutenburg-Richter Distribution')<jupyter_output><empty_output><jupyter_text>We quite frequently want to plot the fit of the a and b values of the gutenburg richter distribution. To do this, we are going to use the equation below which calculates the maximum likelihood of the distribution and returns the parameters:* a - the "productivity" of the distribution, but really just the y-intercept* b - the "mean magnitude" but really it's just the slope* bstdev - the standard deviation of b* length - the number of earthquakes used to calculate the values<jupyter_code>def fmd_values(magnitudes, bin_width=0.1):
    """
    params magnitudes : numpy.array
    params bin_width : float
    
    returns a,b,bstd, n-values if above the earthquake count threshold
    else returns np.nans
    """
    length = magnitudes.shape[0]
    minimum = magnitudes.min()
    average = magnitudes.mean()
    b_value = (1 / (average - (minimum - (bin_width/2)))) * np.log10(np.exp(1))
    square_every_value = np.vectorize(lambda x: x**2)
    b_stddev = square_every_value((magnitudes - average).sum()) / (length * (length - 1))
    b_stddev = 2.3 * np.sqrt(b_stddev) * b_value**2
    a_value = np.log10(length) + b_value * minimum
    
    return a_value, b_value, b_stddev, length
fmd_values(df.Mag.values)
a, b, bstd, n = fmd_values(df.Mag.values)<jupyter_output><empty_output><jupyter_text>Now that we have our values that represent the y-intercept (a value) and the slope (b value), let's plot a fitted line to our data.<jupyter_code>x = np.linspace(0,10, 1000)
y = 10**(a - b*x)
fig, ax = plt.subplots()

ax.plot(edges[:-1], hist, marker='s', color='None', linestyle='')
ax.plot(edges[:-1], chist, marker='^', color='red', linestyle='')

ax.plot(x,y)

ax.set_yscale('log')
ax.set_ylabel('N')
ax.set_xlabel('Magnitude')
ax.set_xlim(4.5, 10)
ax.set_ylim(1e0, 1e5)
ax.set_title('Gutenburg-Richter Distribution')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11617917774596032, 'fraction_numerical': 0.015545101247698916, 'mean_word_length': 5.189873417721519, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '324909', 'license': 'MIT', 'n_tokens_mistral': 1653, 'n_tokens_neox': 1574, 'n_words': 537, 'path': 'example_notebooks/Introduction to scatter plots and histograms.ipynb', 'repo_name': 'mnky9800n/Python-course-materials-for-seismology-students', 'size': '4889'}