Percent Recto vs Verso Cords


1. Percentage Recto and Verso Cords

The ratio of Recto cords to total cords in a khipu. Alternatively 1 - the ratio of Verso cords to total cords.

2. Summary Charts:

Summary Results:

Measure Result
Number of Khipus with Recto/Verso Cord Attachments 325 (50%)
Five most Significant Khipu UR1057, UR087, UR278, UR049, UR016
Image Quilt Click here

Recto Cord Attachments versus Verso Cord Attachments

Code
# Initialize plotly
import plotly
import pandas as pd

plotly.offline.init_notebook_mode(connected = False);

# Read in the Fieldmark and its associated dataframe and match dictionary
from fieldmark_khipu_summary import FieldmarkRectoRatio
from fieldmark_khipu_summary import FieldmarkVersoRatio
#from fieldmark_khipu_summary import FieldmarkMeanCordsPerGroup

aFieldmark = FieldmarkRectoRatio()
recto_matching_khipus = aFieldmark.matching_khipus() 
recto_raw_match_dict = aFieldmark.raw_match_dict()
recto_matching_values = [recto_raw_match_dict[aKhipuName] for aKhipuName in recto_matching_khipus]

aFieldmark = FieldmarkVersoRatio()
verso_matching_khipus = aFieldmark.matching_khipus() 
verso_raw_match_dict = aFieldmark.raw_match_dict()
verso_matching_values = [verso_raw_match_dict[aKhipuName] for aKhipuName in recto_matching_khipus]

matching_df =  pd.DataFrame({'khipu_name':recto_matching_khipus, 
                             'recto_ratio':recto_matching_values, 
                             'verso_ratio':verso_matching_values,})
Code
from plotly import graph_objs as go

fig = (go.Figure()
         .add_trace(go.Bar(x=recto_matching_khipus,
                           y=recto_matching_values,
                           name='Recto Cord Ratios',
                           marker_color='indianred'
                           ))
       .add_trace(go.Bar(x=recto_matching_khipus,
                         y=verso_matching_values,
                         name='Verso Cord Ratios',
                         marker_color='lightsalmon'
                            ))
       .update_layout(barmode='group', width=1500, height=450, xaxis_tickangle=-90).show()
      )

3. Exploratory Data Analysis

3.1 Exploring small numbers of recto cords in predominantly verso cord khipus.

Recto cord attachments exist even in khipus that are primarily verso cords, such as UR153. This is also evident when using the Khipu Fieldmark Brower to sort by Recto ratio or Verso Ratio.

When a khipu is mostly verso-attached cords, recto-attached cords stand out. They often appear to be markers indicating the start or end of a series of verso knot. Let’s pick those khipus that have a recto-cord ratio of 33% or less, and then see - where they lie on their group, and what their ascher color is.

Code
# Khipu Imports
import qollqa_chuspa as qc
# Load khipus
(khipu_dict, all_khipus) = qc.fetch_khipus()
Code
import qollqa_chuspa as qc

khipu_dict, all_khipus = qc.fetch_khipus()

small_khipus = [aKhipu for aKhipu in all_khipus if (recto_raw_match_dict[aKhipu.kfg_name()] <= 33) and (recto_raw_match_dict[aKhipu.kfg_name()] > 0)]
def position_ordinal(x):
    ords = 'zeroth first second third fourth fifth sixth seventh eighth nineth tenth'.split()
    return ords[x] if x < 10 else f"position: {x}"

df_records = []
for aKhipu in small_khipus:
    the_recto_cords = [cord for cord in aKhipu.pendant_cords() if not (cord is None) and cord.is_recto_attachment()]
    for cord in the_recto_cords: 
        cord_position = cord.cord_group.cord_index(cord)
        df_records.append(
            {'kfg_name': aKhipu.kfg_name(),
                'khipu_index':cord.as_index_rep(), 
                'position':cord_position,
                'first_cord': position_ordinal(cord_position+1),
                'last_cord':'last' if cord_position + 1 == cord.cord_group.num_pendant_cords() else position_ordinal(cord_position+1),
                'is_top_cord':'top' if cord.is_top_cord() else "pendant",
                'color':cord.main_color(),
            })

small_recto_df = pd.DataFrame(df_records)
small_recto_df.head(10)
kfg_name khipu_index position first_cord last_cord is_top_cord color
0 HP009 [1, 0] 0 first last pendant W
1 HP015 [0, 0] 0 first first pendant MB
2 HP015 [1, 0] 0 first first pendant MB
3 HP046 A [3, 2] 2 third third pendant W
4 HP046 A [3, 3] 3 fourth last pendant W
5 HP046 A [4, 0] 0 first first pendant W
6 HP046 A [9, 2] 2 third third pendant W
7 HP051 B [0, 0] 0 first first pendant MB
8 HP051 B [1, 0] 0 first first pendant MB
9 HP051 B [7, 0] 0 first first pendant MB
Code
print(f"From {len(small_khipus)} khipus {len(small_recto_df)} cords were found")
from collections import Counter
print(f"\"First\" cords, by position/count: {Counter(list(small_recto_df.first_cord.values)).most_common(7)}")
print(f"\"Last\" cords, by position/count: {Counter(list(small_recto_df.last_cord.values)).most_common(7)}")
print(f"Top cords, by type/count: {Counter(list(small_recto_df.is_top_cord.values)).most_common(2)}")
print(f"Ascher colors, by color/count: {Counter(list(small_recto_df.color.values)).most_common(5)}")
From 60 khipus 668 cords were found
"First" cords, by position/count: [('first', 100), ('second', 80), ('third', 64), ('fourth', 49), ('fifth', 43), ('sixth', 32), ('position: 10', 32)]
"Last" cords, by position/count: [('last', 99), ('first', 83), ('second', 65), ('third', 54), ('fourth', 38), ('fifth', 36), ('sixth', 29)]
Top cords, by type/count: [('pendant', 668)]
Ascher colors, by color/count: [('W', 159), ('MB', 99), ('AB', 66), ('W:MB', 32), ('YB', 25)]
Code
display(small_recto_df)
kfg_name khipu_index position first_cord last_cord is_top_cord color
0 HP009 [1, 0] 0 first last pendant W
1 HP015 [0, 0] 0 first first pendant MB
2 HP015 [1, 0] 0 first first pendant MB
3 HP046 A [3, 2] 2 third third pendant W
4 HP046 A [3, 3] 3 fourth last pendant W
... ... ... ... ... ... ... ...
663 UR1095 [9, 0] 0 first first pendant B
664 UR1095 [9, 1] 1 second second pendant B
665 UR1095 [9, 2] 2 third third pendant B
666 UR1095 [9, 3] 3 fourth fourth pendant B
667 UR1095 [9, 4] 4 fifth last pendant B

668 rows × 7 columns

  • 86 out of 593 (14%) anomalous Recto-attached cords start a group
  • 85 out of 593 (15%) anomalous Recto-attached cords end a group.
  • 145 cords are white. This is lower than the normal distribution of white in khipus (approximately 1/3 of all khipu cords are white). If we increase the number of allowable cords this number goes down even more.

Clearly we should consider the position markers of recto cords (start or end of a group) in a verso-prevalent khipu important. MB and W seem to be fighting it out for dominance, depending on the percentage of allowable recto cords in verso-dominant khipus.

3.2 Exploring small numbers of verso cords in predominantly recto cord khipus.

Let’s similarly, explore the inverse:

Code
small_khipus = [aKhipu for aKhipu in all_khipus if (verso_raw_match_dict[aKhipu.name()] <= 33) and (verso_raw_match_dict[aKhipu.name()] > 0)]
df_records = []

for aKhipu in small_khipus:
    the_verso_cords = [cord for cord in aKhipu.pendant_cords() if not (cord is None) and cord.is_verso_attachment()]
    for cord in the_verso_cords: 
        cord_position = cord.cord_group.cord_index(cord)
        df_records.append({ 'kfg_name': aKhipu.kfg_name(),
                            'khipu_index':cord.as_index_rep(), 
                            'position':cord_position, 
                            'first_cord': position_ordinal(cord_position+1),
                            'last_cord':'last' if cord_position + 1 == cord.cord_group.num_pendant_cords() \
                                               else position_ordinal(cord_position+1),
                            'is_top_cord':'top' if cord.is_top_cord() else "pendant",
                            'color':cord.main_color(),
                        })
        
small_verso_df = pd.DataFrame(df_records)
small_verso_df.head(10)
kfg_name khipu_index position first_cord last_cord is_top_cord color
0 AS075 [14, 4] 4 fifth fifth pendant MB
1 AS199 [0, 0] 0 first first pendant W
2 AS199 [0, 1] 1 second second pendant W
3 AS199 [0, 2] 2 third third pendant W
4 AS199 [0, 3] 3 fourth fourth pendant W
5 AS199 [0, 4] 4 fifth fifth pendant W
6 AS199 [0, 5] 5 sixth sixth pendant W
7 AS199 [0, 6] 6 seventh last pendant W
8 AS199 [2, 1] 1 second second pendant MB:DB
9 AS199 [4, 1] 1 second second pendant W
Code
print(f"From {len(small_khipus)} khipus {len(small_verso_df)} cords were found")
print(f"\"First\" cords, by position/count: {Counter(list(small_verso_df.first_cord.values)).most_common(7)}")
print(f"\"Last\" cords, by position/count: {Counter(list(small_verso_df.last_cord.values)).most_common(7)}")
print(f"Top cords, by type/count: {Counter(list(small_verso_df.is_top_cord.values)).most_common(2)}")
print(f"Ascher colors, by color/count: {Counter(list(small_verso_df.color.values)).most_common(5)}")
From 49 khipus 339 cords were found
"First" cords, by position/count: [('first', 66), ('second', 51), ('third', 46), ('fourth', 37), ('fifth', 30), ('sixth', 25), ('seventh', 15)]
"Last" cords, by position/count: [('last', 63), ('first', 54), ('second', 42), ('third', 37), ('fourth', 34), ('fifth', 25), ('sixth', 19)]
Top cords, by type/count: [('pendant', 339)]
Ascher colors, by color/count: [('W', 71), ('AB', 65), ('MB', 52), ('YB', 31), ('NB', 10)]

In the obverse, recto-dominant khipus with small numbers of verso cords, we see a similar relationship and distribution.

Code
from fieldmark_khipu_summary import FieldmarkKhipuSummary
from plotly import express as px

khipu_summary_df = FieldmarkKhipuSummary().get_khipu_summary_df()
fig = px.scatter(khipu_summary_df, x="num_verso_cords", y="num_recto_cords", log_x=True,
                 size="num_cords", color="num_cords", 
                 labels={"num_verso_cords": "#Verso Cords (log10)", "num_recto_cords": "#Recto Cords"},
                 hover_data=['kfg_name'], title="<b>Verso Cords (log10) vs Recto Cords by Khipu</b>",
                 width=1200, height=750);
(fig.add_shape(type="line", x0=29, y0=1, x1=830, y1=410,
              line=dict(color="MediumPurple",width=4,dash="dot"))
    .add_shape(type="line", x0=29, y0=1, x1=3, y1=330,
              line=dict(color="MediumPurple",width=4,dash="dot"))
    .update_shapes(dict(xref='x', yref='y'))
    .update_layout(width=944, height=944, showlegend=True).show()
)

And yet another view of the complementarity of Recto attached cords and Verso attached cords.

Code
fig = px.scatter(khipu_summary_df, x="num_verso_cords", y="num_recto_cords", log_x=True,
                 size="num_cords", color="num_cords", 
                 labels={"num_verso_cords": "#Verso Cords (log10)", "num_recto_cords": "#Recto Cords"},
                 hover_data=['kfg_name'], title="<b>Verso Cords (log10) vs Recto Cords by Khipu</b>",
                 width=944, height=750);
(fig.add_shape(type="line", x0=29, y0=1, x1=830, y1=410,
              line=dict(color="MediumPurple",width=1,dash="dot"))
    .add_shape(type="line", x0=29, y0=1, x1=3, y1=330,
              line=dict(color="MediumPurple",width=1,dash="dot"))
    .add_shape(type="line", x0=1, y0=0, x1=1, y1=330,
              line=dict(color="MediumPurple",width=1,dash="dot"))
    .add_shape(type="line", x0=2, y0=0, x1=2, y1=330,
              line=dict(color="MediumPurple",width=1,dash="dot"))
    .add_shape(type="line", x0=1, y0=0, x1=900, y1=0,
              line=dict(color="MediumPurple",width=1,dash="dot"))
    .update_shapes(dict(xref='x', yref='y'))
    .update_layout(showlegend=True).show()
)

3.3 Recto/Verso Cords vs Banded/Seriated Khipus

Code
import math

def banded_color(kfg_name): 
    aKhipu = khipu_dict[kfg_name]
    is_banded = aKhipu.num_banded_groups() > khipu_dict[kfg_name].num_seriated_groups()
    return 0.0 if is_banded else 1.0
def banded_ratio(kfg_name):
    aKhipu = khipu_dict[kfg_name]
    total_groups = aKhipu.num_cord_groups()
    return aKhipu.num_banded_groups()/total_groups if total_groups > 0 else 0
def mixed_ratio(kfg_name):
    aKhipu = khipu_dict[kfg_name]
    recto_cords = aKhipu.num_recto_cords()
    verso_cords = aKhipu.num_verso_cords()
    the_ratio = (recto_cords)/(recto_cords + verso_cords + 1)
    if the_ratio and the_ratio > 0.01:
        the_ratio = math.log(the_ratio)
    else:
        the_ratio = 0.0 
    return the_ratio + 5.0 #Hack for plotly graphics package below...
    
cutoff_threshold = 0.05
cutoff_mask = [mixed_ratio(kfg_name) > cutoff_threshold for kfg_name in khipu_summary_df.kfg_name.values]
mixed_summary_df = khipu_summary_df[cutoff_mask]
mixed_summary_df_records = []
for kfg_name in khipu_summary_df.kfg_name.tolist():
    mixed_summary_df_records.append({'kfg_name':kfg_name, 
                                     'num_recto_cords':khipu_dict[kfg_name].num_recto_cords(),
                                     'num_verso_cords':khipu_dict[kfg_name].num_verso_cords(),
                                     'num_banded_groups':khipu_dict[kfg_name].num_banded_groups(),
                                     'num_seriated_groups':khipu_dict[kfg_name].num_seriated_groups(),
                                     'banded_color':banded_color(kfg_name),
                                     'banded_ratio':banded_ratio(kfg_name),
                                     'mixed_ratio':mixed_ratio(kfg_name)})
    
mixed_summary_df = pd.DataFrame(mixed_summary_df_records)
mixed_summary_df.head()
kfg_name num_recto_cords num_verso_cords num_banded_groups num_seriated_groups banded_color banded_ratio mixed_ratio
0 AS001 0 0 1 2 1.0 0.250000 5.0
1 AS002 0 0 0 1 1.0 0.000000 5.0
2 AS003 0 0 2 0 0.0 1.000000 5.0
3 AS004 0 0 6 1 0.0 0.857143 5.0
4 AS005 0 0 1 10 1.0 0.090909 5.0
Code
fig = px.scatter(mixed_summary_df, 
                 x='num_seriated_groups', y='num_banded_groups', 
                 hover_name='kfg_name', hover_data=["num_banded_groups", "num_seriated_groups", "num_recto_cords","num_verso_cords"],
                 size="mixed_ratio",
                 color='banded_color', color_continuous_scale=['#3c3fff', '#ff3030',],
                 labels={"num_recto_cords":"# Recto Cords", 'num_verso_cords':"# Verso Cords"},
                 title=f"<b>Mixed Recto/Verso Cord Khipus by Banded/Seriated</b> - Blue=Banded, Red=Seriated, Size=%Recto Cords", 
                 width=944, height=944).update_coloraxes(showscale=False).show()

This chart shows the use of mixed recto/verso cords is a pattern that occurs in both banded and seriated khipus.

4. Conclusion

In Toward the Decipherment of a Set of Mid-Colonial Khipus from the Santa Valley, Coastal Peru by Manuel Medrano and Gary Urton, it is argued that: >The attachment knots of the first cords of the six-cord groups vary in a binary fashion by attachment type (i.e., tied either “verso” or “recto”). It is argued that this construction feature divides the tributaries identified in the revisit into moieties; therefore, the khipus constitute a gloss on the social organization of the population identified in the revisit document.

This idea, that the first cord acts as a functional marker of some type, becomes evident throughout our investigation of fieldmarks and first cord positions. It becomes apparent, time and time again, that there is a few cords in a group, either at the beginning, or at the end, that have special significance in some functional way. For example, they are attached differently (as this study shows) or they are white instead of similar color to their neighbor, etc. It may be useful to examine first position cords as another source of fieldmarks….