In [1]:
import pandas as pd
import plotly.express
In [2]:
import pathlib
module_dir = next((parent for parent in pathlib.Path.cwd().resolve().parents if (parent / "pyproject.toml").is_file()), None)
In [3]:
df = pd.read_csv(module_dir / "data_files" / "WiFi Strength Vs Distance - 2.4GHz.csv")
In [4]:
df = pd.concat([df, pd.read_csv(module_dir / "data_files" / "WiFi Strength Vs Distance - 5GHz.csv")])
In [5]:
df.head()
Out[5]:
Distance (ft) Signal strength (dBm) - 2.4GHz Signal strength (dBm) - 5GHz
0 1 -22.0 NaN
1 2 -30.0 NaN
2 3 -28.0 NaN
3 3 -34.0 NaN
4 4 -28.0 NaN
In [6]:
df.tail()
Out[6]:
Distance (ft) Signal strength (dBm) - 2.4GHz Signal strength (dBm) - 5GHz
27 50 NaN -87.0
28 60 NaN -80.0
29 70 NaN -79.0
30 80 NaN -92.0
31 90 NaN -92.0
In [7]:
import itertools
In [8]:
keys = list(df.keys())
index = keys[0]
keys = keys[1:]
columns = [index] + [x for y in zip(keys, ['2.4Error', '5Error']) for x in y]

merged_with_error = pd.DataFrame(columns=columns)
In [9]:
merged_with_error.head()
Out[9]:
Distance (ft) Signal strength (dBm) - 2.4GHz 2.4Error Signal strength (dBm) - 5GHz 5Error
In [10]:
distances = sorted(df['Distance (ft)'].unique())
In [11]:
for distance in distances:
    row = {'Distance (ft)': distance}
    for (key, error_key) in [('Signal strength (dBm) - 2.4GHz', '2.4Error'), ('Signal strength (dBm) - 5GHz', '5Error')]:
        values = df.loc[df['Distance (ft)'] == distance][key]
        median = values.median()
        error = max(values.max() - median, median - values.min())
        row[key] = median
        row[error_key] = error
    print(distance, row)
    merged_with_error.loc[distance] = pd.Series(row)

    # merged_with_error.append({k: v for k, v in zip([index] + columns, row)})
    # merged_with_error.loc[distance] = pd.Series({k: v for k, v in zip(columns, row)})
1 {'Distance (ft)': 1, 'Signal strength (dBm) - 2.4GHz': -22.0, '2.4Error': 0.0, 'Signal strength (dBm) - 5GHz': -38.5, '5Error': 0.5}
2 {'Distance (ft)': 2, 'Signal strength (dBm) - 2.4GHz': -30.0, '2.4Error': 0.0, 'Signal strength (dBm) - 5GHz': -54.0, '5Error': 0.0}
3 {'Distance (ft)': 3, 'Signal strength (dBm) - 2.4GHz': -31.0, '2.4Error': 3.0, 'Signal strength (dBm) - 5GHz': -53.0, '5Error': 0.0}
4 {'Distance (ft)': 4, 'Signal strength (dBm) - 2.4GHz': -27.5, '2.4Error': 0.5, 'Signal strength (dBm) - 5GHz': -58.0, '5Error': 0.0}
5 {'Distance (ft)': 5, 'Signal strength (dBm) - 2.4GHz': -31.5, '2.4Error': 0.5, 'Signal strength (dBm) - 5GHz': -58.0, '5Error': 0.0}
6 {'Distance (ft)': 6, 'Signal strength (dBm) - 2.4GHz': -34.5, '2.4Error': 1.5, 'Signal strength (dBm) - 5GHz': -72.0, '5Error': 0.0}
7 {'Distance (ft)': 7, 'Signal strength (dBm) - 2.4GHz': -39.0, '2.4Error': 1.0, 'Signal strength (dBm) - 5GHz': -70.0, '5Error': 0.0}
8 {'Distance (ft)': 8, 'Signal strength (dBm) - 2.4GHz': -42.0, '2.4Error': 4.0, 'Signal strength (dBm) - 5GHz': -64.5, '5Error': 3.5}
9 {'Distance (ft)': 9, 'Signal strength (dBm) - 2.4GHz': -46.0, '2.4Error': 4.0, 'Signal strength (dBm) - 5GHz': nan, '5Error': nan}
10 {'Distance (ft)': 10, 'Signal strength (dBm) - 2.4GHz': -44.0, '2.4Error': 3.0, 'Signal strength (dBm) - 5GHz': -66.5, '5Error': 2.5}
15 {'Distance (ft)': 15, 'Signal strength (dBm) - 2.4GHz': -47.0, '2.4Error': 2.0, 'Signal strength (dBm) - 5GHz': -70.0, '5Error': 4.0}
20 {'Distance (ft)': 20, 'Signal strength (dBm) - 2.4GHz': -53.0, '2.4Error': 1.0, 'Signal strength (dBm) - 5GHz': -72.5, '5Error': 2.5}
25 {'Distance (ft)': 25, 'Signal strength (dBm) - 2.4GHz': -51.0, '2.4Error': 3.0, 'Signal strength (dBm) - 5GHz': nan, '5Error': nan}
30 {'Distance (ft)': 30, 'Signal strength (dBm) - 2.4GHz': -53.5, '2.4Error': 6.5, 'Signal strength (dBm) - 5GHz': -89.0, '5Error': 0.0}
35 {'Distance (ft)': 35, 'Signal strength (dBm) - 2.4GHz': -65.0, '2.4Error': 6.0, 'Signal strength (dBm) - 5GHz': nan, '5Error': nan}
40 {'Distance (ft)': 40, 'Signal strength (dBm) - 2.4GHz': -62.5, '2.4Error': 3.5, 'Signal strength (dBm) - 5GHz': -91.0, '5Error': 0.0}
45 {'Distance (ft)': 45, 'Signal strength (dBm) - 2.4GHz': -64.5, '2.4Error': 3.5, 'Signal strength (dBm) - 5GHz': nan, '5Error': nan}
50 {'Distance (ft)': 50, 'Signal strength (dBm) - 2.4GHz': -65.5, '2.4Error': 5.5, 'Signal strength (dBm) - 5GHz': -87.0, '5Error': 11.0}
60 {'Distance (ft)': 60, 'Signal strength (dBm) - 2.4GHz': -68.0, '2.4Error': 4.0, 'Signal strength (dBm) - 5GHz': -80.0, '5Error': 0.0}
70 {'Distance (ft)': 70, 'Signal strength (dBm) - 2.4GHz': -73.0, '2.4Error': 8.0, 'Signal strength (dBm) - 5GHz': -79.0, '5Error': 0.0}
80 {'Distance (ft)': 80, 'Signal strength (dBm) - 2.4GHz': -73.5, '2.4Error': 4.5, 'Signal strength (dBm) - 5GHz': -92.0, '5Error': 0.0}
90 {'Distance (ft)': 90, 'Signal strength (dBm) - 2.4GHz': -71.0, '2.4Error': 2.0, 'Signal strength (dBm) - 5GHz': -92.0, '5Error': 0.0}
100 {'Distance (ft)': 100, 'Signal strength (dBm) - 2.4GHz': -76.5, '2.4Error': 3.5, 'Signal strength (dBm) - 5GHz': nan, '5Error': nan}
125 {'Distance (ft)': 125, 'Signal strength (dBm) - 2.4GHz': -78.5, '2.4Error': 3.5, 'Signal strength (dBm) - 5GHz': nan, '5Error': nan}
150 {'Distance (ft)': 150, 'Signal strength (dBm) - 2.4GHz': -84.0, '2.4Error': 12.0, 'Signal strength (dBm) - 5GHz': nan, '5Error': nan}
175 {'Distance (ft)': 175, 'Signal strength (dBm) - 2.4GHz': -97.0, '2.4Error': 4.0, 'Signal strength (dBm) - 5GHz': nan, '5Error': nan}
200 {'Distance (ft)': 200, 'Signal strength (dBm) - 2.4GHz': -95.0, '2.4Error': 0.0, 'Signal strength (dBm) - 5GHz': nan, '5Error': nan}
/home/administrator/github/wifi-v-distance-strength-testing/.venv/lib/python3.10/site-packages/numpy/lib/nanfunctions.py:1215: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis, out=out, keepdims=keepdims)
/home/administrator/github/wifi-v-distance-strength-testing/.venv/lib/python3.10/site-packages/numpy/lib/nanfunctions.py:1215: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis, out=out, keepdims=keepdims)
/home/administrator/github/wifi-v-distance-strength-testing/.venv/lib/python3.10/site-packages/numpy/lib/nanfunctions.py:1215: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis, out=out, keepdims=keepdims)
/home/administrator/github/wifi-v-distance-strength-testing/.venv/lib/python3.10/site-packages/numpy/lib/nanfunctions.py:1215: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis, out=out, keepdims=keepdims)
/home/administrator/github/wifi-v-distance-strength-testing/.venv/lib/python3.10/site-packages/numpy/lib/nanfunctions.py:1215: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis, out=out, keepdims=keepdims)
/home/administrator/github/wifi-v-distance-strength-testing/.venv/lib/python3.10/site-packages/numpy/lib/nanfunctions.py:1215: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis, out=out, keepdims=keepdims)
/home/administrator/github/wifi-v-distance-strength-testing/.venv/lib/python3.10/site-packages/numpy/lib/nanfunctions.py:1215: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis, out=out, keepdims=keepdims)
/home/administrator/github/wifi-v-distance-strength-testing/.venv/lib/python3.10/site-packages/numpy/lib/nanfunctions.py:1215: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis, out=out, keepdims=keepdims)
/home/administrator/github/wifi-v-distance-strength-testing/.venv/lib/python3.10/site-packages/numpy/lib/nanfunctions.py:1215: RuntimeWarning: Mean of empty slice
  return np.nanmean(a, axis, out=out, keepdims=keepdims)
In [12]:
merged_with_error.head()
Out[12]:
Distance (ft) Signal strength (dBm) - 2.4GHz 2.4Error Signal strength (dBm) - 5GHz 5Error
1 1.0 -22.0 0.0 -38.5 0.5
2 2.0 -30.0 0.0 -54.0 0.0
3 3.0 -31.0 3.0 -53.0 0.0
4 4.0 -27.5 0.5 -58.0 0.0
5 5.0 -31.5 0.5 -58.0 0.0
In [13]:
merged_with_error.set_index('Distance (ft)')
Out[13]:
Signal strength (dBm) - 2.4GHz 2.4Error Signal strength (dBm) - 5GHz 5Error
Distance (ft)
1.0 -22.0 0.0 -38.5 0.5
2.0 -30.0 0.0 -54.0 0.0
3.0 -31.0 3.0 -53.0 0.0
4.0 -27.5 0.5 -58.0 0.0
5.0 -31.5 0.5 -58.0 0.0
6.0 -34.5 1.5 -72.0 0.0
7.0 -39.0 1.0 -70.0 0.0
8.0 -42.0 4.0 -64.5 3.5
9.0 -46.0 4.0 NaN NaN
10.0 -44.0 3.0 -66.5 2.5
15.0 -47.0 2.0 -70.0 4.0
20.0 -53.0 1.0 -72.5 2.5
25.0 -51.0 3.0 NaN NaN
30.0 -53.5 6.5 -89.0 0.0
35.0 -65.0 6.0 NaN NaN
40.0 -62.5 3.5 -91.0 0.0
45.0 -64.5 3.5 NaN NaN
50.0 -65.5 5.5 -87.0 11.0
60.0 -68.0 4.0 -80.0 0.0
70.0 -73.0 8.0 -79.0 0.0
80.0 -73.5 4.5 -92.0 0.0
90.0 -71.0 2.0 -92.0 0.0
100.0 -76.5 3.5 NaN NaN
125.0 -78.5 3.5 NaN NaN
150.0 -84.0 12.0 NaN NaN
175.0 -97.0 4.0 NaN NaN
200.0 -95.0 0.0 NaN NaN
In [14]:
fig = plotly.express.scatter(merged_with_error, x='Distance (ft)', y='Signal strength (dBm) - 2.4GHz', error_y=merged_with_error.columns[2], log_x=True,
                            trendline="ols", trendline_options=dict(log_x=True),
                            )
fig.show()
In [15]:
fig = plotly.express.scatter(
    merged_with_error, x='Distance (ft)', y='Signal strength (dBm) - 5GHz',
    error_y=merged_with_error.columns[4], log_x=True,
    trendline="ols", trendline_options=dict(log_x=True),
)
fig.show()
In [16]:
import pathlib

def make_plot(df: pd.DataFrame, x: str, y: str, error_index: int, out_file: pathlib.Path, first: bool, series_title: str):
    fig = plotly.express.scatter(df, x=x, y=y, error_y=df.columns[error_index],
                                 # log_x=True,
                            trendline="ols", trendline_options=dict(log_x=True),
                            title=f"Median Wi-Fi Strength (dBm) Vs Distance (ft) - {series_title}",
                            )
    fig.show()
    if first:
        out_file.write_text("")
    with out_file.open("a", encoding="UTF-8") as fout:
        fout.write(fig.to_html(out_file, full_html=first))
In [17]:
out_file = pathlib.Path("report.html")
import numpy

make_plot(merged_with_error, x='Distance (ft)', y='Signal strength (dBm) - 2.4GHz', error_index=2, out_file=out_file, first=True, series_title="2.4 GHz")
make_plot(merged_with_error.loc[merged_with_error['Distance (ft)'] < 100], x='Distance (ft)', y='Signal strength (dBm) - 5GHz', error_index=4, out_file=out_file, first=False, series_title="5 GHz")
In [ ]:
 
In [ ]: