1. LOCATION of Pendant Pendant Sums Over the Whole Khipu:
When looking at the sum relationship image quilt for this fieldmark, it is interesting to note how often right/left-handed relationships have the sum cord close to their respective ends of the khipu. Let’s graph group positions for right/left-handed sums.
Since, the number of cords in a khipu varies, we’ll normalize the sum cord location by dividing by the number of pendant cords.
First let’s get a simple lay of the land with a few scatterplots:
One showing position (from the left) of right handed sums by group and cord position,
One showing right-handed sums, from the left, and
One showing left-handed sums, offset from the right.
Code
#=======================================================# INITIALIZE# Read in the Fieldmark and its associated dataframes#=======================================================import pandas as pdimport numpy as npimport plotlyimport plotly.graph_objs as goimport plotly.express as pximport utils_loom as uloomimport utils_khipu as ukhipuimport qollqa_chuspa as qc from statistics import mean, modeimport warningswarnings.filterwarnings('ignore')warnings.simplefilter('ignore')from fieldmark_ascher_pendant_pendant_sum import FieldmarkPendantPendantSumaFieldmark = FieldmarkPendantPendantSum()khipu_df = aFieldmark.dataframes[0].dataframesum_cord_df = aFieldmark.dataframes[1].dataframe(khipu_dict, all_khipus) = qc.fetch_khipus()# Initialize plotlyplotly.offline.init_notebook_mode(connected =False);
Code
left_handed_sums_df = sum_cord_df[sum_cord_df.handedness <0]right_handed_sums_df = sum_cord_df[sum_cord_df.handedness >=0] left_handed_khipu_names = ukhipu.lexigraphic_order(list(set(left_handed_sums_df.kfg_name.tolist()))) right_handed_khipu_names = ukhipu.lexigraphic_order(list(set(right_handed_sums_df.kfg_name.tolist())))right_handed_locations = []left_handed_locations = []for aKhipuName in left_handed_khipu_names: num_pendant_cords =float(khipu_dict[aKhipuName].num_pendant_cords()) left_handed_sum_cords = aFieldmark.sum_cords(khipu_dict[aKhipuName], left_handed=True, right_handed=False) normalized_left_handed_sum_cords = [float(ukhipu.pendant_cord_index_from_cord_name(cord.cord_name))/float(num_pendant_cords) for cord in left_handed_sum_cords] left_handed_locations.extend(normalized_left_handed_sum_cords)for aKhipuName in right_handed_khipu_names: num_pendant_cords =float(khipu_dict[aKhipuName].num_pendant_cords()) right_handed_sum_cords = aFieldmark.sum_cords(khipu_dict[aKhipuName], left_handed=False, right_handed=True) normalized_right_handed_sum_cords = [float(ukhipu.pendant_cord_index_from_cord_name(cord.cord_name))/float(num_pendant_cords) for cord in right_handed_sum_cords] right_handed_locations.extend(normalized_right_handed_sum_cords)left_handed_locations =sorted(left_handed_locations)right_handed_locations =sorted(right_handed_locations)fig = px.histogram(pd.DataFrame({'left_handed_locations': left_handed_locations}), x="left_handed_locations", width=944, title="Histogram of Normalized Left Handed Sum Locations for Pendant-Pendant Sums").show()fig = px.histogram(pd.DataFrame({'right_handed_locations': right_handed_locations}), x="right_handed_locations", width=944, title="Histogram of Normalized Right Handed Sum Locations for Pendant-Pendant Sums").show()
2. Locations Of Left & Right-Handed Sum Cords by Group:
2.1 Counts of Group Locations
Looking at the sum relationship image quilt for this fieldmark, it is interesting to note how often left-handed relationships have the sum cord at the right end of the khipu. Let’s graph group positions for left-handed and right-handed sums.
Code
left_handed_sums_df = sum_cord_df[sum_cord_df.handedness <0]right_handed_sums_df = sum_cord_df[sum_cord_df.handedness >=0] left_handed_khipu_names = ukhipu.lexigraphic_order(list(set(left_handed_sums_df.kfg_name.tolist()))) right_handed_khipu_names = ukhipu.lexigraphic_order(list(set(right_handed_sums_df.kfg_name.tolist())))right_handed_group_locations = []left_handed_group_locations = []for aKhipuName in left_handed_khipu_names: num_groups = khipu_dict[aKhipuName].num_groups() left_handed_sum_cords = aFieldmark.sum_cords(khipu_dict[aKhipuName], left_handed=True, right_handed=False) left_handed_sum_cords_group_locations = [(num_groups-1) - aCord.cord_group.position_index for aCord in left_handed_sum_cords] left_handed_group_locations.extend(left_handed_sum_cords_group_locations)for aKhipuName in right_handed_khipu_names: right_handed_sum_cords = aFieldmark.sum_cords(khipu_dict[aKhipuName], left_handed=False, right_handed=True) right_handed_sum_cords_group_locations = [aCord.cord_group.position_index for aCord in right_handed_sum_cords] right_handed_group_locations.extend(right_handed_sum_cords_group_locations)right_handed_group_locations =sorted(right_handed_group_locations)left_handed_group_locations =sorted(left_handed_group_locations)fig = px.histogram(pd.DataFrame({'left_handed_group_locations': left_handed_group_locations}), x="left_handed_group_locations", width=944, title="Histogram of Left Handed Sum Group Locations for Pendant-Pendant Sums - <b>From Right End of Khipu</b>").show()fig = px.histogram(pd.DataFrame({'right_handed_group_locations': right_handed_group_locations}), x="right_handed_group_locations", width=944, title="Histogram of Right Handed Sum Group Locations for Pendant-Pendant Sums - <b>From Left End of Khipu</b>").show()
Let’s zoom in on that… Remember that left-handed sums are indexed by the distance from the right, not the left.
Code
right_handed_group_locations = [location for location in right_handed_group_locations if location <50 ]left_handed_group_locations = [location for location in left_handed_group_locations if location <50 ]fig = (px.histogram(pd.DataFrame({'left_handed_group_locations': left_handed_group_locations}), x="left_handed_group_locations", width=944, title="Partial Histogram - Left Handed Pendant-Pendant Sums Group Locations (From The Right)") .update_layout(xaxis =dict( tickmode ='linear', tick0 =0, dtick =5 )).show())fig = (px.histogram(pd.DataFrame({'right_handed_group_locations': right_handed_group_locations}), x="right_handed_group_locations", width=944, title="Partial Histogram - Right Handed Pendant-Pendant Sums Group Locations") .update_layout(xaxis =dict( tickmode ='linear', tick0 =0, dtick =5 )).show())
Observations:
As expected the largest set of Right-handed sum cords are in the first group, first cord position. Many of these come from smaller khipus.
Left handed sum cords occur about half the time that right handed sum cords occur.
Note the interesting spikes at index 3 (4th position from right), and 5 (6th position from right) for left-handed sums.
2.2 How Often are Pendant Sums Grouped Together on A Group?
It appears, visually, that most sum cords lie together in a group. Is that true? For each khipu what is the percentage of sums that are solitary and non contiguous?
Let’s examine the search space, first, for khipus that have two or more sum cords on a group, where the sum cords are non-contiguous.
Code
left_handed_sums_df = sum_cord_df[sum_cord_df.handedness <0]right_handed_sums_df = sum_cord_df[sum_cord_df.handedness >=0] left_handed_khipu_names = ukhipu.lexigraphic_order(list(set(left_handed_sums_df.kfg_name.tolist()))) right_handed_khipu_names = ukhipu.lexigraphic_order(list(set(right_handed_sums_df.kfg_name.tolist())))right_handed_group_counts = {num_groups : 0for num_groups inrange(1, 31)}left_handed_group_counts = {num_groups : 0for num_groups inrange(1, 31)}for aKhipuName in left_handed_khipu_names: left_handed_sum_cords = aFieldmark.sum_cords(khipu_dict[aKhipuName], left_handed=True, right_handed=False) left_handed_sum_cords_group_locations =sorted([(num_groups-1) - aCord.cord_group.position_index for aCord in left_handed_sum_cords])for aGroupList in uloom.split_list(left_handed_sum_cords_group_locations):iflen(aGroupList) >1: # Skip 1 sum length groups (khipus that have two or more sum cords) left_handed_group_counts[len(aGroupList)] = left_handed_group_counts[len(aGroupList)] +1for aKhipuName in right_handed_khipu_names: right_handed_sum_cords = aFieldmark.sum_cords(khipu_dict[aKhipuName], left_handed=False, right_handed=True) right_handed_sum_cords_group_locations =sorted([aCord.cord_group.position_index for aCord in right_handed_sum_cords])for aGroupList in uloom.split_list(right_handed_sum_cords_group_locations):iflen(aGroupList) >1: # Skip 1 sum length groups (khipus that have two or more sum cords) right_handed_group_counts[len(aGroupList)] = right_handed_group_counts[len(aGroupList)] +1left_handed_group_df = pd.DataFrame(zip(left_handed_group_counts.keys(), left_handed_group_counts.values()), columns =['# Of Sums Per Group', 'Occurences'])fig = px.bar(left_handed_group_df, x='# Of Sums Per Group', y='Occurences', log_y=True, title=f"# of Left-Handed Sums Per Group for Pendant Pendant Sums", width=944, height=750).update_layout(showlegend=True).show()right_handed_group_df = pd.DataFrame(zip(right_handed_group_counts.keys(), right_handed_group_counts.values()), columns =['# Of Sums Per Group', 'Occurences'])fig = px.bar(right_handed_group_df, x='# Of Sums Per Group', y='Occurences', log_y=True, title=f"# of Right-Handed Sums Per Group for Pendant Pendant Sums", width=944, height=750).update_layout(showlegend=True).show()total_left_handed_sums =sum(left_handed_group_counts.values()) theLeftPctCumArray = np.cumsum(np.array(list(left_handed_group_counts.values())))/total_left_handed_sumscum_left_handed_group_df = pd.DataFrame(zip(left_handed_group_counts.keys(), theLeftPctCumArray), columns =['# Of Sums Per Group', 'Cumulative Occurences'])fig = px.bar(cum_left_handed_group_df, x='# Of Sums Per Group', y='Cumulative Occurences', log_y=True, title=f"Cumulative # of Left-Handed Sums Per Group for Pendant Pendant Sums", width=944, height=750).update_layout(showlegend=True).show()total_right_handed_sums =sum(right_handed_group_counts.values()) theRightPctCumArray = np.cumsum(np.array(list(right_handed_group_counts.values())))/total_right_handed_sumscum_right_handed_group_df = pd.DataFrame(zip(right_handed_group_counts.keys(), theRightPctCumArray), columns =['# Of Sums Per Group', 'Cumulative Occurences'])fig = px.bar(cum_right_handed_group_df, x='# Of Sums Per Group', y='Cumulative Occurences', log_y=True, title=f"Cumulative # of Right-Handed Sums Per Group for Pendant Pendant Sums", width=944, height=750).update_layout(showlegend=True).show()
Slightly over half (53% as noted above) of khipu sum cords lie together in a group. Let’s call these groups “sum groups”.
3 Position of Sum Cords In A Group
3.1 What Positions are Sum Cords in a Group
Code
left_handed_sums_df = sum_cord_df[sum_cord_df.handedness <0]right_handed_sums_df = sum_cord_df[sum_cord_df.handedness >=0] left_handed_khipu_names = ukhipu.lexigraphic_order(list(set(left_handed_sums_df.kfg_name.tolist()))) right_handed_khipu_names = ukhipu.lexigraphic_order(list(set(right_handed_sums_df.kfg_name.tolist())))left_handed_group_cord_index_locations = []right_handed_group_cord_index_locations = []for aKhipuName in left_handed_khipu_names: left_handed_sum_cords = aFieldmark.sum_cords(khipu_dict[aKhipuName], left_handed=True, right_handed=False) group_cord_index_locations = [(aCord.group_index(), aCord.cord_group.num_pendant_cords()) for aCord in left_handed_sum_cords] left_handed_group_cord_index_locations.extend(group_cord_index_locations)for aKhipuName in right_handed_khipu_names: right_handed_sum_cords = aFieldmark.sum_cords(khipu_dict[aKhipuName], left_handed=False, right_handed=True) group_cord_index_locations = [(aCord.group_index(), aCord.cord_group.num_pendant_cords()) for aCord in right_handed_sum_cords] right_handed_group_cord_index_locations.extend(group_cord_index_locations)left_handed_group_cord_index_locations =sorted(left_handed_group_cord_index_locations, key=lambda x: x[0])right_handed_group_cord_index_locations =sorted(right_handed_group_cord_index_locations, key=lambda x: x[0])from collections import Counternum_left_handed_cords_in_position = Counter([x[0] for x in left_handed_group_cord_index_locations])left_handed_tuples = [(cord_index, num_pendants, num_left_handed_cords_in_position[cord_index]) for (cord_index, num_pendants) in left_handed_group_cord_index_locations]left_handed_group_cord_index_locations_df = pd.DataFrame(left_handed_tuples, columns=['cord_group_index', 'num_pendant_cords', 'num_cords_by_index'])num_right_handed_cords_in_position = Counter([x[0] for x in right_handed_group_cord_index_locations])right_handed_tuples = [(cord_index, num_pendants, num_right_handed_cords_in_position[cord_index]) for (cord_index, num_pendants) in right_handed_group_cord_index_locations]right_handed_group_cord_index_locations_df = pd.DataFrame(right_handed_tuples, columns=['cord_group_index', 'num_pendant_cords', 'num_cords_by_index'])plot_title ="# of Cords by Position in Group for Left-handed Pendant-Pendant Sums"fig = (px.scatter(left_handed_group_cord_index_locations_df, x="num_pendant_cords", y="cord_group_index", log_y=True, color="num_cords_by_index", labels={"num_cords_by_index": "#Cords in Position in Group", "cord_group_index": "Cord Position in Group", "num_pendant_cords": "# of Pendant Cords in Group",}, title=plot_title, width=944, height=944) .update_layout(showlegend=True).update(layout_coloraxis_showscale=True).show() )plot_title ="# of Cords by Position in Group for Right-handed Pendant-Pendant Sums"fig = (px.scatter(right_handed_group_cord_index_locations_df, x="num_pendant_cords", y="cord_group_index", log_y=True, color="num_cords_by_index", labels={"num_cords_by_index": "#Cords in Position in Group", "cord_group_index": "Cord Position in Group", "num_pendant_cords": "# of Pendant Cords in Group",}, title=plot_title, width=944, height=944) .update_layout(showlegend=True).update(layout_coloraxis_showscale=True).show() )
3.2 Color of First Cord in Group
In groups which have a sum cord, what is the first cord color?
Code
grouped_sum_cords = (aFieldmark.group_sum_cords_by_group_index())lh_color_dict = {}rh_color_dict = {}for aGrouped_List in grouped_sum_cords: the_khipu = khipu_dict[aGrouped_List['kfg_name']]for aGroup in aGrouped_List['lh_cord_reps']: first_color = aFieldmark.first_color(the_khipu, aGroup) lh_color_dict[first_color] = lh_color_dict.get(first_color, 0) +1for aGroup in aGrouped_List['rh_cord_reps']: first_color = aFieldmark.first_color(the_khipu, aGroup) rh_color_dict[first_color] = rh_color_dict.get(first_color, 0) +1lh_color_df = pd.DataFrame(list(lh_color_dict.items()), columns =['Ascher Color', 'Count']).sort_values(by=['Count'], ascending=False)rh_color_df = pd.DataFrame(list(rh_color_dict.items()), columns =['Ascher Color', 'Count']).sort_values(by=['Count'], ascending=False)fig = px.bar(lh_color_df, x='Ascher Color', y='Count', log_y=True, title=f"Color Occurence of First Cord in Group for Left-Handed Pendant Pendant Sums", width=944, height=750).update_layout(showlegend=True).show()fig = px.bar(rh_color_df, x='Ascher Color', y='Count', log_y=True, title=f"Color Occurence of First Cord in Group for Right-Handed Pendant Pendant Sums", width=944, height=750).update_layout(showlegend=True).show()
Let’s Zoom in on the top colors for each handedness
Code
grouped_sum_cords = (aFieldmark.group_sum_cords_by_group_index())lh_color_dict = {}rh_color_dict = {}for aGrouped_List in grouped_sum_cords: the_khipu = khipu_dict[aGrouped_List['kfg_name']]for aGroup in aGrouped_List['lh_cord_reps']: first_color = aFieldmark.first_color(the_khipu, aGroup) lh_color_dict[first_color] = lh_color_dict.get(first_color, 0) +1for aGroup in aGrouped_List['rh_cord_reps']: first_color = aFieldmark.first_color(the_khipu, aGroup) rh_color_dict[first_color] = rh_color_dict.get(first_color, 0) +1top_lh_color_dict = {k: v for k, v in lh_color_dict.items() if v >5 }top_rh_color_dict = {k: v for k, v in rh_color_dict.items() if v >5 }lh_color_df = pd.DataFrame(list(top_lh_color_dict.items()), columns =['Ascher Color', 'Count']).sort_values(by=['Count'], ascending=False)rh_color_df = pd.DataFrame(list(top_rh_color_dict.items()), columns =['Ascher Color', 'Count']).sort_values(by=['Count'], ascending=False)fig = px.bar(lh_color_df, x='Ascher Color', y='Count', log_y=True, title=f"Color Occurence of First Cord in Group for Left-Handed Pendant Pendant Sums", width=944, height=750).update_layout(showlegend=True).show()fig = px.bar(rh_color_df, x='Ascher Color', y='Count', log_y=True, title=f"Color Occurence of First Cord in Group for Right-Handed Pendant Pendant Sums", width=944, height=750).update_layout(showlegend=True).show()
How does this compare to overall khipu pendant color distribution?
Code
all_pendant_color_dict = {}for aKhipu in all_khipus: pendant_cords = aKhipu.pendant_cords()for aCord in pendant_cords: all_pendant_color_dict[aCord.main_color()] = all_pendant_color_dict.get(aCord.main_color(), 0) +1all_pendant_color_dict = uloom.sort_dict_by_values(all_pendant_color_dict)lh_color_dict = uloom.sort_dict_by_values(lh_color_dict)rh_color_dict = uloom.sort_dict_by_values(rh_color_dict)num_pendant_colors =sum(all_pendant_color_dict.values())num_lh_pendant_colors =sum(lh_color_dict.values())num_rh_pendant_colors =sum(rh_color_dict.values()) print(f"Percent Left-handed sum White cord colors= {uloom.as_percent_string(lh_color_dict['W'], num_lh_pendant_colors)} vs All pendant White cord colors= {uloom.as_percent_string(all_pendant_color_dict['W'], num_pendant_colors)}")print(f"Percent Right-handed sum White cord colors= {uloom.as_percent_string(rh_color_dict['W'], num_rh_pendant_colors)} vs All pendant White cord colors= {uloom.as_percent_string(all_pendant_color_dict['W'], num_pendant_colors)}")
Percent Left-handed sum White cord colors= 29.2% vs All pendant White cord colors= 25.9%
Percent Right-handed sum White cord colors= 29.1% vs All pendant White cord colors= 25.9%
When looking at the first cord of a sum cord group for colored-pendant sum, chances are close to 29% that it’s white, somewhat higher odds than the overall chances of a white pendant in general (26%). Again, like the similar calculation in colored-pendant sums, this speaks, albeit softly, in support of the argument that white is a grammatical marker for sums - not as a marker for addition, but as a tag indicating a sum group.
4. Span of Right-handed vs Left-handed Sums
An examination of the frequency of handedness in the sum cords reveals that right handed sums span a wider distance than left handed sums, as you would suspect.
Code
legend_text ="<b>Handedness Frequency by Sum</b>"fig = (px.violin(sum_cord_df, y="handedness", points='all', hover_data=['kfg_name', 'cord_index', 'num_summands', 'handedness'], title=legend_text, width=944, height=944).show())
5. Summand Locations vs. Sum Cord Location
Let’s graph the mean of summand locations (as a cord index from the left) vs the sum cord location (as a cord index from the left).
Code
# Start from the top again.sum_distance_df = aFieldmark.dataframes[1].dataframe# Remove AS069sum_distance_df = sum_distance_df[sum_distance_df.kfg_name !="AS069"]
Code
khipus = [khipu_dict[aName] for aName inlist(sum_distance_df.kfg_name.values)]summand_strings =list(sum_distance_df.summand_string.values)summand_mean_index = []cord_names =list(sum_distance_df.cord_name.values)cord_positions = []for (record_index, summand_string) inenumerate(summand_strings): aKhipu = khipus[record_index] sum_cord = aKhipu[cord_names[record_index]] cord_positions.append(sum_cord.pendant_index()) summand_cords = aFieldmark.cords_from_sum_string(aKhipu, summand_string, one_based=False) summand_indexes = [aCord.pendant_index() for aCord in summand_cords] summand_mean_position =round(mean(summand_indexes) iflen(summand_indexes) >0else0) summand_mean_index.append(summand_mean_position)sum_distance_df['cord_position'] = cord_positionssum_distance_df['summand_mean_index'] = summand_mean_indexsum_distance_df['distance'] = [cord_positions[i]-summand_mean_index[i] for i inrange(len(summand_mean_index))]def handed_color(x): return0.0if x <0else1.0sum_distance_df['handed_color'] = [handed_color(x) for x in sum_distance_df.handedness.values]
Code
title_str=f"<b>Sum Cord Position vs. mean(Summand Cord Positions)</b>"+\" : Red is Right Handed, Blue is Left-Handed"fig = (px.scatter(sum_distance_df, x="cord_position", y="summand_mean_index", color="handed_color", color_continuous_scale=['#3c3fff', '#ff3030',], labels={"handed_color":"Handedness of Sum Cord Value","cord_value":"Sum Cord Value","cord_position":"Sum Cord Position", "summand_mean_index": "Mean of Summand Cord Positions", "num_summands": "#Summands"}, hover_name='kfg_name', hover_data=['cord_position', 'summand_mean_index', 'cord_value', 'num_summands'], title=title_str, width=944, height=944) .update_layout(showlegend=False) .update(layout_coloraxis_showscale=False) .show() )
This is as you would expect :-)
6. Pendant-Pendant Sum Group Neighbors
Visually, it appears that many sum groups have a 0 value group neighboring them.Let’s see if that’s the case.
Code
num_left_zeros =0num_right_zeros =0num_both_zeros =0num_no_zeros =0num_sum_groups =0def is_all_zero_pendant_cord_group(aGroup):return aGroup andall([cord.knotted_value ==0for cord in aGroup.pendant_cords()])for aKhipu in aFieldmark.all_khipus(): all_sum_groups = uloom.unique(aFieldmark.sum_groups(aKhipu, left_handed=True, right_handed=True)) num_sum_groups +=len(all_sum_groups)for sum_group in all_sum_groups: the_group_khipu = sum_group.khipu is_zero_left_group = is_all_zero_pendant_cord_group(the_group_khipu.left_group_neighbor(sum_group)) is_zero_right_group = is_all_zero_pendant_cord_group(the_group_khipu.right_group_neighbor(sum_group)) num_left_zeros +=1if is_zero_left_group else0 num_right_zeros +=1if is_zero_right_group else0 num_both_zeros +=1if is_zero_left_group and is_zero_right_group else0 num_no_zeros +=1if (not is_zero_left_group) and (not is_zero_right_group) else0print(f"{uloom.as_percent_string(num_left_zeros, num_sum_groups)} of Sum Groups have a 0-sum cord group to their Left")print(f"{uloom.as_percent_string(num_right_zeros, num_sum_groups)} of Sum Groups have a 0-sum cord group to their Right")print(f"{uloom.as_percent_string(num_both_zeros, num_sum_groups)} of Sum Groups have a 0-sum cord group on BOTH their Left and Right")print(f"{uloom.as_percent_string(num_no_zeros, num_sum_groups)} of Sum Groups have a NON-ZERO sum cord group on BOTH their Left and Right")
13.6% of Sum Groups have a 0-sum cord group to their Left
13.9% of Sum Groups have a 0-sum cord group to their Right
8.2% of Sum Groups have a 0-sum cord group on BOTH their Left and Right
80.7% of Sum Groups have a NON-ZERO sum cord group on BOTH their Left and Right
7. Conclusions:
Right handed sums span a wider range of cords then left-handed sums.
Right-handed sums occur on the left side of the khipu
Left-handed sums occur on the right side of the khipu
As expected the largest set of Right-handed sum cords are in the first group, first cord position. Many of these come from smaller khipus.
Left handed sum cords occur about ⅔ the time that right handed sum cords occur.
Pendant pendant sum cords group together ~50% of the time. This grouping is called a sum group.
Sum groups also group together with other sum groups. 81% of Sum Groups have a NON-ZERO sum cord group on BOTH their Left and Right.
In highly banded khipus, sum groups are often bordered by zero-valued cord groups.
The use of White, as a first cord color in a group, which occurs 29% of the time (higher than its overall average of 26%) may indicate that it belongs to a sum group.