I assume that you want to calculate the mutual information between each p1 and each of p2 , p3 , ... afterwards.
1) Calculate H(X) as the entropy from p1 with:

each x is the next element of p1 .
2) Calculate H(Y) as the entropy of pK with the same equation, with each x being the next element of p1
3) Create a new pair of p1 and pK :
pairs = zip(p1, pK)
Note that if the values ββin the columns of your data have different meanings, you should probably fill in the missing data (for example, using 0 or the values ββfrom the previous iteration).
4) Calculate the entropy of the joints H(X,Y) using:

Note that you cannot just use the first equation and treat each pair as one element - you must iterate over the entire Cartesian product between p1 and pK in this equation, calculating the probabilities using the pairs collection. So, to iterate over the entire Cartesian product, use for xy in itertools.product(p1, pK): ...
5) Then you can have mutual information between p1 and pK as:

Using the capabilities of numpy, you can calculate the total entropy presented here here :
def entropy(X, Y): probs = [] for c1 in set(X): for c2 in set(Y): probs.append(np.mean(np.logical_and(X == c1, Y == c2))) return np.sum(-p * np.log2(p) for p in probs if p > 0)
where if p > 0 is consistent with the definition of entropy :
In the case p (x i ) = 0 for some i, the value of the corresponding term 0 log b (0) is taken equal to 0
If you do not want to use numpy , then the version without it might look something like this:
def entropyPart(p): if not p: return 0 return -p * math.log(p) def entropy(X, Y): pairs = zip(X, Y) probs = [] for pair in itertools.product(X,Y): probs.append(1.0 * sum([p == pair for p in pairs]) / len(pairs)) return sum([entropyPart(p) for p in probs])