Subsidiary cords that are Sums of a set of Primary cord Pendant cords.
2. Search Criteria:
Here again, there is a balance between precision and recall. We limit searches to where the subsidiary cord has a value of at least 5, and where the summand cords are contiguous. Furthermore, for summation candidates, the maximum moving search window size is set to 250 contiguous (except for 0-value cords) at a time.
In the never ending struggle to dial it just right, the search is limited to pendant cords with a value of at least 11, and where the summand cords are contiguous for at least three cords (not including 0 cords in-between). Furthermore, for summation candidates, the maximum moving search window size is set to 250 contiguous (except for 0-value cords) at a time.
What to do about off-by-one errors, where for example 483 should match 493? Although off-by-one knot errors occur frequently, in this particular study, unlike top cords, Sums are not matched on an off-by-one digit basis and instead an exact numerical match is required. This reduces the number of found pendant sums from 2422 (allowing off by one errors) to 2210. Once again, we are trading off recall for precision.
Additional culling is done. When a subsidiary can match more than one set of summands, the shortest one is chosen. When a subsidiary is under 100, and is a multiple of 10, it is not chosen.
3. Significance Criteria:
Probably we should set significance based on cord value. For now, we simply look at the number of subsidiary cords that sum…
# Initialize plotlyimport plotlyplotly.offline.init_notebook_mode(connected =False);# Read in the Fieldmark and its associated dataframe and match dictionaryfrom fieldmark_ascher_subsidiary_pendant_sum import FieldmarkSubsidiaryPendantSumaFieldmark = FieldmarkSubsidiaryPendantSum()fieldmark_dataframe = aFieldmark.dataframes[0].dataframeraw_match_dict = aFieldmark.raw_match_dict()
Code
# Plot Matching khipuimport plotly.express as pximport pandas as pdmatching_khipus = aFieldmark.matching_khipus() matching_values = [raw_match_dict[aKhipuName] for aKhipuName in matching_khipus]matching_df = pd.DataFrame(list(zip(matching_khipus, matching_values)), columns =['KhipuName', 'Value'])fig = px.bar(matching_df, x='KhipuName', y='Value', labels={"KhipuName": "Khipu Name", "Value": "Number of Subsidiary Pendant Sum Cords", }, title=f"Matching Khipu ({len(matching_khipus)}) for Number of Subsidiary Pendant Sum Cords", width=944, height=450).update_layout(showlegend=True).show()
Code
# Plot Significant khipusignificant_khipus = aFieldmark.significant_khipus()significant_values = [raw_match_dict[aKhipuName] for aKhipuName in significant_khipus]significant_df = pd.DataFrame(list(zip(significant_khipus, significant_values)), columns =['KhipuName', 'Value'])fig = px.bar(significant_df, x='KhipuName', y='Value', labels={"KhipuName": "Khipu Name", "Value": "Number of Subsidiary Pendant Sum Cords", }, title=f"Significant Khipu ({len(significant_khipus)}) for Number of Subsidiary Pendant Sum Cords", width=944, height=450).update_layout(showlegend=True).show()
Code
significant_values = [raw_match_dict[aKhipuName] for aKhipuName in significant_khipus]significant_df = pd.DataFrame(list(zip(significant_khipus, significant_values)), columns =['KhipuName', 'Value'])fig = px.bar(significant_df, x='KhipuName', y='Value', labels={"KhipuName": "Khipu Name", "Value": "Number of Subsidiary Pendant Sum Cords", }, title=f"Significant Khipu ({len(significant_khipus)}) for Number of Subsidiary Pendant Sum Cords", width=944, height=450).update_layout(showlegend=True).show()
6. Exploratory Data Analysis:
6.1 Handedness
Code
import utils_khipu as ukhipuimport qollqa_chuspa as qcpd.options.mode.chained_assignment =None# default='warn'sum_cord_df = aFieldmark.dataframes[1].dataframesum_cord_df['group_index'] = [ukhipu.group_index_from_cord_rep(aString) for aString in sum_cord_df.cord_index.values]right_sum_cord_index_df = sum_cord_df[sum_cord_df.handedness >=0]left_sum_cord_index_df = sum_cord_df[sum_cord_df.handedness <0]# This is a special case correction for subsidiaryright_sum_cord_index_df['cord_index'] = [ukhipu.cord_index_from_cord_rep(aString) for aString in right_sum_cord_index_df.cord_index.values]left_sum_cord_index_df['cord_index'] = [ukhipu.cord_index_from_cord_rep(aString) for aString in left_sum_cord_index_df.cord_index.values]num_right_sums =len(right_sum_cord_index_df) num_left_sums =len(left_sum_cord_index_df) num_sums = num_right_sums + num_left_sumsright_pct =round(100.0*float(num_right_sums)/float(num_sums))left_pct =round(100.0*float(num_left_sums)/float(num_sums))print(f"Out of {num_sums} subsidiary pendant sums, there are {num_right_sums}({right_pct}%) right_handed sums and {num_left_sums}({left_pct}%) left-handed sums")
Out of 873 subsidiary pendant sums, there are 505(58%) right_handed sums and 368(42%) left-handed sums
Code
def handed_color(x): return0.0if x <0else1.0sum_cord_df['handed_color'] = [handed_color(x) for x in sum_cord_df.handedness.values]fig = (px.scatter(sum_cord_df, x="num_summands", y="cord_value", log_y=True, color='handed_color', color_continuous_scale=['#3c3fff', '#ff3030',], size="num_summands", labels={"num_summands": "Number of contiguous cords in sum", "cord_value": "Sum Cord Value (Log(y) scale)"}, hover_data=['kfg_name', 'cord_value', 'num_summands', 'handedness'], title="<b>Subsidiary Pendant Sums</b> - <i>Red is Right-Handed: Hover Over Circles to View Khipu/Cord Info</i>", width=944, height=944) .update_layout(showlegend=False).update(layout_coloraxis_showscale=False).show() )
Code
from statistics import meanhandedness_mean = mean(list(sum_cord_df.handedness.values))fig = (px.scatter(sum_cord_df, x="handedness", y="cord_value", log_y=True, size="num_summands", color='handed_color', color_continuous_scale=['#3c3fff', '#ff3030',], labels={"handedness": f"Handedness - Mean({handedness_mean})", "cord_value": "Cord Value (Log(y) scale)", }, hover_data=['kfg_name'], title="<b>Handedness of Subsidiary Pendant Sums</b> - <i>Red is Right-Handed: Hover Over Circles to View Khipu/Cord Info</i>", width=944, height=944) .add_vline(x=handedness_mean) .update_layout(showlegend=False).update(layout_coloraxis_showscale=False).show() )
Let’s try that again without AS069:
Code
not_as069_df = sum_cord_df[sum_cord_df.kfg_name !="AS069"]fig = (px.scatter(not_as069_df, x="handedness", y="cord_value", log_y=True, size="num_summands", color='handed_color', color_continuous_scale=['#3c3fff', '#ff3030',], labels={"handedness": f"Handedness - Mean({handedness_mean})", "cord_value": "Cord Value (Log(y) scale)", }, hover_data=['kfg_name'], title="<b>Handedness of Subsidiary Pendant Sums Without AS069</b> - <i>Red is Right-Handed: Hover Over Circles to View Khipu/Cord Info</i>", width=944, height=944) .add_vline(x=handedness_mean) .update_layout(showlegend=False).update(layout_coloraxis_showscale=False).show() )
Once again, we see an even distribution of sums both the left and to the right.
make_heatmap_array(right_sum_cord_index_df, max_num_groups=30, max_num_cords=50, title="<b>Top occurrences</b> of RIGHT-HANDED</b> Subsidiary Pendant Sum Positions (O Based Indexing)", is_right_handed=True)make_heatmap_array(left_sum_cord_index_df, max_num_groups=30, max_num_cords=50, title="<b>Top occurrences</b> of <b>LEFT-HANDED</b> Subsidiary Pendant Sum Positions (from the right - O Based Indexing)", is_right_handed=False)
6.2 Sum and Summand Cords
Code
fig = (px.scatter(sum_cord_df, y="cord_value", x="num_summands", log_y=True,#size="cord_value", color="cord_value", labels={"num_summands":"# Summands", "group_index":"Cluster Index (0 based)", "cord_index": "Cord Index (0 Based)", "cord_value": "Cord Value"}, hover_name='kfg_name', hover_data=['group_index', 'cord_index', 'cord_value', 'num_summands'], title="<b>Subsidiary Pendant Sums:</b> Cord Value vs Number Summands - <i>Hover Over Circles to View Khipu/Cord Info</i>", width=944, height=944) .update_layout(showlegend=True) .show() )
7. Conclusion
We could cut and paste the conclusions from indexed pendant sums, and it would almost be correct :-)
Once again, we see the classic 60/40 split between right and left-handed sums, although here it is 57% to 43%. This consistent 60/40 split across all four sum relations is astonishing.
Dropping AS069 gives us more insight into the distance between sums and summands. It’s not that large. When the outlier AS069 is dropped, the distance between summands and sum cord follows a roughly triangular distribution - Large sum cord values are close to their summands, and small sum cord values can be farther away (1-30 cords) from their summands.
Subsidiary pendant sums follow the same overall location distribution that pendant-pendant sums, pendant-color sums, and color pendant sums follow.