I have the following numpy 3d array:
mat.data['Sylvain_2015'].shape = (180, 12, 15)
This array is populated with a variable (muscle activation) for each participant (first dimension: 180), for each muscle (second dimension: 12), for each condition (third dimension: 15).
I want to transform this array to the following pandas dataframe:
muscle participant activation test
0 1 1 100.000000 1
1 1 1 69.322225 2
2 1 1 84.917656 3
3 1 1 80.983069 4
4 1 1 65.163384 5
5 1 1 30.528706 6
Is there a more efficient way than with three for loops:
participants, muscles, tests, relative_mvc = ([] for i in range(4))
for iparticipant in range(mat.data[idataset].shape[0]):
for imuscle in range(mat.data[idataset].shape[1]):
max_mvc = np.nanmax(mat.data[idataset][iparticipant, imuscle, :])
for itest in range(mat.data[idataset].shape[2]):
participants.append(iparticipant+1)
datasets.append(idataset)
muscles.append(imuscle+1)
tests.append(itest+1)
# normalize mvc (relative to max)
activation.append(mat.data[idataset][iparticipant, imuscle, itest]*100/max_mvc)
df = pd.DataFrame({
'participant': participants,
'dataset': datasets,
'muscle': muscles,
'test': tests,
'relative_mvc': relative_mvc,
}).dropna()
Here is a sample of the 3d array for two participants (created with this useful post)
# Array shape: (2, 12, 15)
0.13 0.09 0.11 0.11 0.09 0.04 0.03 0.06 0.11 0.09 0.03 0.10 0.01 0.03 0.08
0.21 0.36 0.34 0.18 0.25 0.23 0.11 0.05 0.27 0.27 0.13 0.26 0.04 0.02 0.34
0.16 0.09 0.41 0.28 0.20 0.10 0.16 0.04 0.15 0.25 0.04 0.18 0.02 0.09 0.24
nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
0.09 0.09 0.10 0.09 0.08 0.05 0.01 0.02 0.08 0.07 0.08 0.08 0.01 0.02 0.09
0.17 0.39 0.33 0.21 0.17 0.29 0.06 0.01 0.21 0.25 0.27 0.22 0.03 0.01 0.31
0.01 0.01 0.01 0.03 0.01 0.01 0.03 0.06 0.01 0.01 0.04 0.01 0.03 0.06 0.01
0.06 0.01 0.07 0.07 0.07 0.03 0.06 0.12 0.09 0.08 0.04 0.04 0.04 0.03 0.10
0.01 0.03 0.02 0.01 0.01 0.11 0.10 0.01 0.01 0.01 0.09 0.01 0.04 0.01 0.02
0.10 0.10 0.14 0.11 0.08 0.03 0.01 0.02 0.05 0.06 0.01 0.09 0.01 0.01 0.10
0.05 0.03 0.06 0.08 0.08 0.01 0.03 0.02 0.03 0.04 0.02 0.07 0.00 0.02 0.06
0.04 0.05 0.03 0.02 0.08 0.03 0.02 0.02 0.06 0.05 0.02 0.06 0.03 0.01 0.02
# New slice
0.21 0.08 0.15 0.11 0.15 0.05 0.01 0.01 0.06 0.04 0.02 0.13 0.02 0.02 0.16
0.26 0.14 0.18 0.12 0.22 0.10 0.10 0.07 0.12 0.17 0.09 0.18 0.03 0.02 0.13
0.10 0.13 0.13 0.05 0.08 0.08 0.08 0.03 0.03 0.06 0.10 0.06 0.05 0.02 0.05
nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
0.11 0.08 0.10 0.07 0.10 0.05 0.02 0.02 0.05 0.03 0.03 0.10 0.05 0.04 0.10
0.13 0.20 0.18 0.12 0.12 0.17 0.03 0.01 0.12 0.10 0.12 0.15 0.09 0.04 0.16
0.02 0.01 0.01 0.06 0.03 0.01 0.03 0.06 0.02 0.01 0.04 0.04 0.04 0.05 0.04
0.02 0.02 0.04 0.03 0.05 0.04 0.07 0.03 0.04 0.01 0.02 0.06 0.03 0.03 0.03
0.02 0.03 0.02 0.02 0.02 0.07 0.04 0.02 0.01 0.01 0.04 0.02 0.03 0.02 0.02
0.07 0.11 0.14 0.03 0.04 0.08 0.01 0.01 0.10 0.11 0.01 0.02 0.01 0.01 0.02
0.03 0.02 0.03 0.05 0.04 0.01 0.01 0.02 0.01 0.03 0.01 0.04 0.01 0.01 0.03
0.04 0.05 0.03 0.03 0.04 0.06 0.02 0.01 0.01 0.03 0.05 0.03 0.03 0.02 0.02
# New slice
I can think of a couple of ways. Here is one way without using loops, where make a Panel first, and then convert to dataframe.
# normalize values first
max_values = np.nanmax(mat.data[idataset], axis=2)
values = mat.data[idataset]*100/max_values.reshape(max_values.shape +(1,))
# get sizes
iparticipant, imuscle, itest = mat.data[idataset].shape
# set axes labels
items = np.arange(1, 1+iparticipant)
major_axis = np.arange(1, imuscle+1)
minor_axis = np.arange(1, itest + 1)
# make a panel (3-d dataframe)
panel = pd.Panel(values, items=iparticipant, major_axis=major_axis, minor_axis=minor_axis)
# covert to dataframe and fix column labels
df = panel.to_frame().stack().reset_index()
df.columns = ['muscle', 'test', 'participant', 'relative_mvc']
df['dataset'] = idataset
Related
I am trying to create a kmeans algorithm that is based on the Earth Movers Distance instead of the Euclidean distance. However, when I run it, it just returns the same value for all data points.
The input is an dxn matrix containing all of my n probability distributions.
Here is an example of running the algorithm. The clusters for my data of length 169 should be much more distributed. I've also tried running it for more iterations to no avail.
distribution = {}
num_bins = 10
for i in data:
distribution[i] = np.histogram(data[i], bins = num_bins)[0] / len(data[i])
Z = np.zeros((len(data), num_bins))
for i in range(len(Z)):
Z[i] = distribution[list(distribution)[i]]
Z = Z.T
ans = k_means_algorithm(Z, 8, proportionally_random_k)
res = points_to_clusters(Z, ans)
print(res)
[[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 1. 3. 0. 0. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 4. 1. 0. 4. 1. 1. 1. 4. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 4. 2. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0.
1. 1. 1. 1. 1. 1. 1. 1. 0. 1. 0. 1. 0. 1. 1. 1. 1. 3. 1. 1. 1. 1. 0. 0.
1. 0. 1. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1.]]
Here is my code:
def k_random(X, k):
random_idx = np.random.permutation(X.shape[1])
centroids = X[:, random_idx[:k]]
return centroids
def points_to_clusters(X, centroids):
assignment = np.zeros(len(X[0]))
for i in range(len(X[0])):
min_dist = 100000000
for j in range(len(centroids[0])):
cur_dist = scipy.stats.wasserstein_distance(X[:, i], centroids[:, j])
#cur_dist = np.linalg.norm(X[:, I] - centroids[:, j])
#EMD vs Norm
if cur_dist < min_dist:
assignment[i] = j
min_dist = cur_dist
assignment = np.array([assignment])
return assignment
def compute_centroids(X, k, cluster_assignments, old_centroids):
dimensions = X.shape[0]
centroids = np.zeros((dimensions, k))
for j in range(k):
new_centroid = np.mean(X[:, cluster_assignments.squeeze()==j], axis=1)
if np.isnan(new_centroid).any():
centroids[:,j] = old_centroids[:,j]
else:
centroids[:,j] = np.mean(X[:, cluster_assignments.squeeze()==j], axis=1)
return centroids
def k_means_algorithm(X, k, random_init, max_iters = 1000, return_obj=False):
centroids = random_init(X,k)
cluster_assignments = points_to_clusters(X, centroids)
new_centroids = compute_centroids(X, k, cluster_assignments, centroids)
counter = 0
while not np.array_equal(centroids,new_centroids) and counter < max_iters:
centroids = new_centroids
cluster_assignments = points_to_clusters(X, centroids)
new_centroids = compute_centroids(X, k, cluster_assignments, centroids)
counter += 1
return centroids
def proportionally_random_k(X, k):
centroids = [X[:, np.random.randint(X.shape[1])]]
for other_centroids in range(k - 1):
distances = []
for i in range(X.shape[1]):
point = X[:, i]
d = float("inf")
for j in range(len(centroids)):
temp_dist = np.linalg.norm(point - centroids[j])
d = min(d, temp_dist)
distances.append(d)
distances = np.array(distances)
next_centroid = X[:, np.argmax(distances)]
centroids.append(next_centroid)
distances = []
return np.asarray(centroids).T
Here is my answer when running the Norm vs EMD.
k_means_algorithm(Z, 8, k_random, max_iters=1000)
Note that the only thing that changes between the two codes is the line that is highlighted in the function points_to_clusters, which specifies which points get mapped to what clusters.
Norm: About what I expected, well distributed clusters.
[[6. 6. 6. 6. 6. 6. 6. 6. 0. 0. 0. 0. 4. 4. 2. 2. 2. 2. 2. 2. 2. 2. 7. 7.
6. 6. 6. 6. 6. 6. 0. 0. 0. 0. 4. 4. 2. 2. 2. 2. 2. 2. 2. 2. 7. 7. 6. 6.
6. 6. 0. 6. 0. 0. 0. 4. 2. 2. 2. 2. 2. 2. 2. 2. 7. 2. 6. 6. 0. 0. 0. 0.
4. 4. 2. 2. 5. 4. 2. 2. 2. 2. 7. 7. 0. 0. 0. 4. 4. 4. 4. 4. 2. 4. 2. 2.
5. 5. 7. 7. 4. 4. 4. 4. 5. 5. 5. 5. 5. 5. 5. 5. 7. 7. 4. 4. 5. 4. 5. 5.
5. 5. 5. 5. 7. 3. 5. 5. 5. 5. 3. 3. 3. 3. 3. 3. 5. 5. 3. 3. 3. 5. 3. 3.
3. 3. 3. 3. 3. 3. 3. 3. 3. 3. 3. 3. 7. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
3.]]
EMD: Gave the same cluster to all distributions. Clearly not right. It should be much more distributed.
[[2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.
2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.
2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.
2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.
2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.
2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.
2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.
2.]]
Here is a sample of the data that I used when running the above cluster function.
[[0.41 0.46 0.35 0.45 0.39 0.42 0.38 0.38 0.27 0.29 0.24 0.3 0.18 0.19
0.07 0.12 0.1 0.09 0.06 0.09 0.07 0.05 0.03 0.05 0.35 0.4 0.36 0.42
0.36 0.43 0.31 0.31 0.22 0.29 0.16 0.18 0.06 0.11 0.06 0.05 0.1 0.06
0.06 0.06 0.06 0.02 0.39 0.35 0.34 0.38 0.31 0.36 0.23 0.23 0.24 0.2
0.12 0.07 0.06 0.06 0.06 0.05 0.03 0.03 0.05 0.03 0.38 0.39 0.29 0.32
0.26 0.24 0.17 0.17 0.07 0.1 0.03 0.1 0.05 0.06 0.05 0.03 0.02 0.03
0.29 0.37 0.24 0.21 0.16 0.15 0.11 0.1 0.13 0.14 0.03 0.06 0.03 0.13
0.03 0.03 0.14 0.18 0.17 0.11 0.08 0.09 0.07 0.04 0.05 0.03 0.04 0.02
0.03 0.04 0.16 0.15 0.1 0.09 0.03 0.1 0.03 0.06 0.06 0.06 0.03 0.01
0.09 0.07 0.06 0.08 0.03 0.04 0.02 0.01 0.02 0.03 0.06 0.04 0.04 0.04
0.04 0.04 0.03 0.04 0.05 0.03 0.04 0.03 0.03 0.04 0.04 0.01 0.01 0.05
0.02 0.01 0.03 0.02 0.01 0.01 0.01 0.03 0.01 0.02 0.01 0.01 0. 0.02
0.01]
[0.04 0.03 0.04 0.05 0.06 0.05 0.05 0.04 0.15 0.16 0.18 0.2 0.22 0.22
0.21 0.22 0.14 0.16 0.19 0.17 0.1 0.09 0.12 0.14 0.04 0.04 0.03 0.04
0.04 0.06 0.13 0.14 0.2 0.23 0.24 0.23 0.18 0.19 0.13 0.18 0.14 0.17
0.1 0.1 0.13 0.13 0.02 0.05 0.04 0.05 0.12 0.11 0.14 0.21 0.19 0.25
0.18 0.19 0.1 0.21 0.19 0.19 0.1 0.12 0.13 0.18 0.03 0.07 0.13 0.11
0.12 0.2 0.25 0.23 0.21 0.23 0.13 0.21 0.18 0.19 0.1 0.09 0.15 0.12
0.11 0.11 0.21 0.19 0.13 0.28 0.21 0.19 0.15 0.24 0.23 0.17 0.1 0.14
0.1 0.14 0.24 0.26 0.22 0.23 0.18 0.2 0.12 0.19 0.12 0.14 0.11 0.08
0.11 0.14 0.18 0.22 0.2 0.24 0.13 0.14 0.11 0.14 0.11 0.1 0.16 0.04
0.21 0.21 0.07 0.09 0.06 0.08 0.04 0.09 0.06 0.03 0.1 0.11 0.08 0.07
0.08 0.1 0.06 0.04 0.07 0.11 0.05 0.07 0.08 0.06 0.11 0.04 0.07 0.08
0.04 0.05 0.03 0.02 0.02 0.01 0.02 0.02 0.01 0.02 0.02 0.01 0.02 0.02
0. ]
[0.03 0.02 0.02 0.02 0.02 0.02 0.02 0.01 0.03 0.03 0.01 0.01 0.07 0.09
0.12 0.15 0.14 0.15 0.09 0.17 0.21 0.2 0.09 0.09 0.03 0.01 0.01 0.02
0.02 0.04 0.03 0.01 0.02 0.03 0.06 0.06 0.18 0.15 0.13 0.15 0.13 0.17
0.18 0.23 0.07 0.09 0.01 0.02 0.02 0.02 0.02 0.01 0.03 0.03 0.05 0.04
0.14 0.15 0.15 0.13 0.18 0.18 0.21 0.18 0.1 0.1 0.01 0.02 0.01 0.01
0.02 0.02 0.04 0.06 0.12 0.15 0.18 0.08 0.16 0.14 0.22 0.23 0.1 0.08
0. 0.01 0.01 0.02 0.06 0.06 0.1 0.13 0.11 0.08 0.16 0.15 0.19 0.08
0.11 0.1 0.02 0.02 0.05 0.07 0.13 0.17 0.12 0.19 0.16 0.17 0.22 0.22
0.13 0.09 0.05 0.06 0.15 0.13 0.15 0.16 0.17 0.13 0.17 0.25 0.08 0.2
0.12 0.12 0.18 0.16 0.14 0.14 0.11 0.14 0.12 0.16 0.18 0.19 0.14 0.12
0.12 0.14 0.09 0.13 0.14 0.14 0.14 0.13 0.13 0.1 0.16 0.1 0.1 0.11
0.13 0.18 0.1 0.08 0.05 0.07 0.03 0.06 0.06 0.02 0.01 0.03 0.01 0.02
0.02]
[0.07 0.11 0.08 0.07 0.07 0.06 0.06 0.1 0.06 0.05 0.07 0.05 0.06 0.05
0.05 0.05 0.11 0.11 0.09 0.1 0.12 0.14 0.3 0.26 0.05 0.06 0.05 0.05
0.05 0.04 0.03 0.05 0.03 0.02 0.04 0.06 0.08 0.04 0.12 0.11 0.1 0.1
0.14 0.12 0.21 0.25 0.04 0.05 0.07 0.04 0.03 0.04 0.05 0.05 0.06 0.05
0.08 0.07 0.1 0.1 0.06 0.06 0.08 0.09 0.19 0.13 0.03 0.04 0.03 0.02
0.04 0.03 0.05 0.04 0.05 0.05 0.1 0.08 0.05 0.07 0.06 0.11 0.23 0.23
0.04 0.03 0.02 0.02 0.03 0.01 0.03 0.05 0.09 0.04 0.1 0.07 0.11 0.11
0.21 0.21 0.03 0.02 0.03 0.02 0.05 0.04 0.09 0.1 0.06 0.1 0.07 0.16
0.17 0.16 0.03 0.02 0.03 0.03 0.1 0.08 0.14 0.1 0.12 0.08 0.17 0.13
0.02 0.04 0.07 0.08 0.15 0.16 0.16 0.12 0.2 0.17 0.06 0.07 0.13 0.13
0.12 0.1 0.17 0.16 0.15 0.16 0.07 0.15 0.19 0.17 0.08 0.16 0.15 0.18
0.09 0.15 0.27 0.17 0.1 0.09 0.07 0.06 0.06 0.11 0.12 0.08 0.02 0.03
0.02]
[0.13 0.12 0.13 0.11 0.14 0.1 0.09 0.13 0.08 0.13 0.12 0.09 0.13 0.08
0.1 0.09 0.09 0.12 0.13 0.09 0.09 0.09 0.01 0.04 0.11 0.14 0.11 0.14
0.09 0.11 0.11 0.12 0.07 0.06 0.06 0.09 0.13 0.08 0.1 0.1 0.09 0.09
0.09 0.11 0.05 0.08 0.1 0.1 0.11 0.08 0.06 0.11 0.09 0.06 0.08 0.06
0.1 0.06 0.1 0.07 0.08 0.05 0.12 0.11 0.07 0.1 0.08 0.04 0.06 0.07
0.08 0.06 0.05 0.09 0.07 0.07 0.05 0.08 0.08 0.08 0.12 0.13 0.06 0.07
0.03 0.03 0.04 0.05 0.05 0.05 0.05 0.05 0.07 0.04 0.06 0.08 0.05 0.05
0.06 0.07 0. 0.02 0.05 0.03 0.06 0.03 0.03 0.03 0.05 0.05 0.06 0.04
0.07 0.06 0.04 0.03 0.04 0.04 0.04 0.03 0.06 0.08 0.05 0.05 0.03 0.09
0.02 0.02 0.06 0.01 0.04 0.07 0.06 0.1 0.06 0.08 0.03 0.01 0.04 0.06
0.1 0.11 0.06 0.07 0.03 0.03 0.11 0.14 0.07 0.08 0.09 0.13 0.08 0.06
0.09 0.1 0.21 0.24 0.31 0.25 0.18 0.18 0.22 0.22 0.15 0.13 0.07 0.08
0.01]
[0.13 0.09 0.09 0.09 0.11 0.14 0.14 0.11 0.15 0.12 0.09 0.12 0.09 0.11
0.07 0.07 0.11 0.09 0.09 0.08 0.09 0.1 0.09 0.08 0.15 0.11 0.15 0.13
0.15 0.13 0.11 0.13 0.15 0.1 0.1 0.1 0.1 0.11 0.08 0.08 0.06 0.08
0.1 0.06 0.09 0.07 0.13 0.17 0.13 0.17 0.16 0.14 0.13 0.13 0.08 0.13
0.11 0.1 0.1 0.09 0.07 0.12 0.07 0.09 0.09 0.11 0.16 0.16 0.14 0.15
0.11 0.15 0.1 0.11 0.1 0.11 0.09 0.11 0.07 0.09 0.09 0.09 0.05 0.09
0.15 0.12 0.11 0.12 0.16 0.12 0.1 0.1 0.12 0.13 0.09 0.13 0.07 0.08
0.09 0.07 0.12 0.13 0.1 0.11 0.08 0.06 0.08 0.07 0.09 0.08 0.08 0.1
0.07 0.12 0.07 0.04 0.05 0.05 0.07 0.05 0.05 0.05 0.09 0.07 0.08 0.06
0.02 0.03 0.04 0.02 0.05 0.03 0.05 0.07 0.05 0.07 0.03 0.02 0.02 0.02
0.03 0.05 0.04 0.05 0.02 0.02 0.03 0.02 0.05 0.05 0.02 0.03 0.04 0.04
0.04 0.04 0.12 0.15 0.16 0.21 0.31 0.3 0.26 0.2 0.21 0.24 0.11 0.17
0.05]
[0.02 0.04 0.02 0.06 0.03 0.07 0.06 0.06 0.05 0.05 0.07 0.06 0.08 0.09
0.07 0.06 0.05 0.05 0.07 0.08 0.04 0.06 0.03 0.02 0.07 0.05 0.05 0.06
0.06 0.05 0.05 0.1 0.09 0.09 0.07 0.08 0.08 0.06 0.06 0.1 0.06 0.04
0.02 0.05 0.02 0.04 0.05 0.09 0.08 0.06 0.07 0.1 0.11 0.11 0.08 0.09
0.06 0.12 0.09 0.09 0.06 0.07 0.06 0.07 0.05 0.04 0.09 0.08 0.12 0.11
0.13 0.12 0.09 0.1 0.12 0.09 0.11 0.1 0.1 0.09 0.05 0.04 0.06 0.05
0.14 0.13 0.13 0.13 0.12 0.13 0.13 0.14 0.09 0.11 0.09 0.09 0.07 0.1
0.04 0.07 0.16 0.14 0.17 0.15 0.09 0.15 0.14 0.12 0.13 0.1 0.1 0.09
0.09 0.05 0.17 0.16 0.12 0.13 0.12 0.13 0.09 0.11 0.07 0.1 0.08 0.07
0.17 0.15 0.13 0.16 0.09 0.1 0.08 0.07 0.11 0.09 0.13 0.12 0.08 0.1
0.07 0.1 0.05 0.08 0.06 0.08 0.07 0.02 0.04 0.07 0.04 0.02 0.04 0.06
0.05 0.07 0.03 0.09 0.1 0.12 0.08 0.11 0.11 0.16 0.18 0.16 0.24 0.22
0.06]
[0.01 0.02 0.03 0.02 0.05 0.06 0.03 0.05 0.03 0.03 0.05 0.07 0.04 0.05
0.08 0.1 0.09 0.1 0.07 0.12 0.09 0.11 0.1 0.1 0.03 0.05 0.03 0.04
0.04 0.04 0.04 0.04 0.03 0.06 0.07 0.06 0.05 0.1 0.1 0.12 0.1 0.14
0.09 0.1 0.11 0.1 0.04 0.03 0.03 0.06 0.03 0.03 0.06 0.05 0.06 0.07
0.04 0.08 0.11 0.1 0.1 0.11 0.11 0.12 0.11 0.15 0.03 0.09 0.06 0.07
0.06 0.03 0.07 0.07 0.08 0.08 0.12 0.1 0.1 0.09 0.1 0.11 0.12 0.14
0.06 0.06 0.05 0.07 0.07 0.05 0.07 0.06 0.05 0.1 0.07 0.11 0.11 0.16
0.11 0.12 0.07 0.06 0.05 0.08 0.13 0.12 0.1 0.1 0.08 0.13 0.15 0.11
0.09 0.13 0.1 0.14 0.08 0.11 0.11 0.11 0.1 0.11 0.11 0.13 0.12 0.12
0.1 0.16 0.13 0.19 0.12 0.14 0.15 0.13 0.1 0.1 0.18 0.18 0.12 0.16
0.12 0.14 0.16 0.13 0.14 0.17 0.13 0.14 0.11 0.1 0.11 0.14 0.08 0.08
0.08 0.05 0.01 0.02 0.04 0.06 0.09 0.04 0.09 0.07 0.09 0.13 0.24 0.2
0.34]
[0.04 0.01 0.05 0.03 0.04 0.03 0.03 0.04 0.04 0.03 0.05 0.02 0.04 0.04
0.08 0.03 0.04 0.06 0.06 0.04 0.08 0.1 0.1 0.11 0.04 0.04 0.05 0.05
0.02 0.04 0.04 0.02 0.06 0.06 0.06 0.05 0.04 0.06 0.06 0.05 0.07 0.08
0.11 0.09 0.13 0.11 0.04 0.06 0.03 0.03 0.08 0.05 0.04 0.05 0.03 0.03
0.05 0.06 0.07 0.08 0.08 0.08 0.11 0.11 0.08 0.08 0.04 0.03 0.04 0.04
0.04 0.04 0.05 0.06 0.05 0.04 0.08 0.06 0.1 0.09 0.1 0.06 0.12 0.11
0.05 0.03 0.05 0.08 0.06 0.07 0.05 0.06 0.07 0.06 0.06 0.08 0.1 0.08
0.14 0.1 0.04 0.05 0.04 0.08 0.06 0.06 0.08 0.08 0.1 0.11 0.07 0.07
0.1 0.14 0.06 0.07 0.06 0.06 0.08 0.08 0.1 0.12 0.1 0.08 0.15 0.18
0.08 0.07 0.07 0.1 0.11 0.12 0.14 0.13 0.12 0.17 0.08 0.13 0.15 0.13
0.15 0.12 0.16 0.2 0.18 0.11 0.17 0.18 0.15 0.21 0.23 0.25 0.26 0.23
0.27 0.25 0.03 0.02 0.04 0.03 0.04 0.05 0.05 0.05 0.07 0.06 0.1 0.09
0.27]
[0.12 0.1 0.18 0.1 0.1 0.06 0.14 0.08 0.13 0.11 0.11 0.08 0.1 0.07
0.17 0.1 0.14 0.07 0.14 0.05 0.11 0.06 0.13 0.1 0.13 0.1 0.17 0.07
0.16 0.07 0.15 0.08 0.13 0.06 0.12 0.09 0.11 0.09 0.16 0.07 0.15 0.08
0.12 0.08 0.13 0.12 0.18 0.1 0.16 0.11 0.12 0.05 0.12 0.09 0.14 0.08
0.12 0.09 0.12 0.07 0.12 0.08 0.12 0.09 0.12 0.09 0.14 0.08 0.12 0.11
0.14 0.12 0.12 0.08 0.12 0.09 0.09 0.07 0.11 0.1 0.11 0.12 0.08 0.08
0.14 0.13 0.13 0.1 0.15 0.09 0.15 0.12 0.13 0.07 0.11 0.05 0.17 0.07
0.11 0.09 0.18 0.12 0.13 0.11 0.15 0.08 0.17 0.09 0.14 0.1 0.11 0.11
0.14 0.08 0.15 0.11 0.15 0.11 0.17 0.12 0.15 0.1 0.12 0.09 0.1 0.09
0.16 0.12 0.19 0.11 0.19 0.11 0.19 0.14 0.16 0.1 0.15 0.13 0.2 0.16
0.17 0.11 0.16 0.11 0.15 0.15 0.18 0.12 0.16 0.12 0.12 0.12 0.16 0.12
0.19 0.12 0.17 0.18 0.18 0.15 0.17 0.15 0.13 0.12 0.14 0.15 0.19 0.14
0.22]]
There is nothing wrong with the code. But: The standard/best known k-means algorithm is Lloyd's algorithm (this also seems to be the version presented in the question). It assigns points to clusters using the Euclidean distance (kind of per definition). This distance measure cannot be simply replaced by another.
See for example the compute_centroids() function. Here new centroids are calculated using the mean values of the cluster points (thus k-means). By doing so it is implicitely assumed that this new centroid is a better representative of the cluster then the previous one as it minimises the overall distance between the points of the cluster to the centroid. But this needn't be the case if the distance function is changed.
There are other variations using for example the median which could be combined with the Manhattan distance.
See this question for a far more detailed discussion.
Quick addition to the algorithm to print out the cluster assignment distribution during each iteration
# imports ...
np.set_printoptions(precision=1)
# ...
def k_means_algorithm(X, k, random_init, max_iters = 1000, return_obj=False):
# ...
while not np.array_equal(centroids,new_centroids) and counter < max_iters:
# ...
hist, bin_edges = np.histogram(cluster_assignments.flatten(), bins=k)
hist = 100 * hist / hist.sum()
print(hist) # percentage of values assigned to each cluster
return centroids, cluster_assignments
# ...
Caution: this only gives a rough impression how values are assigned to clusters and might level out for the full scale data set. Still, it works nicely for the sample data provided with the question.
While the distribution more or less steadily converges to the final solution in case cur_dist = np.linalg.norm(X[:, i] - centroids[:, j]) is used,
it 'jumps' around for cur_dist = wasserstein_distance(X[:, i], centroids[:, j]) for said reason that the centroids do not represent the centers of the clusters for the EMD.
I have reset the indexed already. My FFT peak
0.12667
0.12
0.11667
0.10333
0.1
0.096667
0.093333
0.09
0.09
0.09
0.086667
0.086667
0.083333
0.083333
0.083333
0.076667
0.076667
0.073333
0.073333
0.073333
0.07
0.07
0.07
0.07
0.066667
0.066667
0.063333
0.06
0.06
0.056667
0.056667
0.056667
0.056667
0.056667
0.053333
0.05
0.05
0.05
0.05
0.05
0.05
0.05
0.05
0.046667
0.046667
0.046667
0.046667
0.043333
0.043333
0.043333
0.04
0.04
0.04
0.04
0.04
0.04
0.04
0.04
0.04
0.04
0.04
Its is one of the column in dataframe.
and i am trying to find outliers in it before applying classifier
here is my function to find outlier
def outliers(x):
return np.abs(x- x.median()) > 1.5*(x.quantile(.75)-x.quantile(0.25))
def replace(x):
out = x[outliers(x)]
return x.replace(to_replace = [out.min(),out.max()],
value = [np.percentile(x,5),np.percentile(x,95)])
X1o = X3_a.apply(replace)
Try converting your column to a float object before apply
Ex:
import pandas as pd
X1o = pd.to_numeric(X3_a, errors='coerce').apply(replace)
I have the below assumed dataframe
a b c d e F
0.02 0.62 0.31 0.67 0.27 a
0.30 0.07 0.23 0.42 0.00 a
0.82 0.59 0.34 0.73 0.29 a
0.90 0.80 0.13 0.14 0.07 d
0.50 0.62 0.94 0.34 0.53 d
0.59 0.84 0.95 0.42 0.54 d
0.13 0.33 0.87 0.20 0.25 d
0.47 0.37 0.84 0.69 0.28 e
Column F represents the columns of the dataframe.
For each row of column F I want to find relevant row and column from the rest of the dataframe and return the values into one column
The outcome will look like this:
a b c d e f To_Be_Filled
0.02 0.62 0.31 0.67 0.27 a 0.02
0.30 0.07 0.23 0.42 0.00 a 0.30
0.82 0.59 0.34 0.73 0.29 a 0.82
0.90 0.80 0.13 0.14 0.07 d 0.14
0.50 0.62 0.94 0.34 0.53 d 0.34
0.59 0.84 0.95 0.42 0.54 d 0.42
0.13 0.33 0.87 0.20 0.25 d 0.20
0.47 0.37 0.84 0.69 0.28 e 0.28
I am able to identify each case with the below, but not sure how to do it across the whole dataframe.
test.loc[test.iloc[:,5]==a,test.columns==a]
Many thanks in advance.
You can use lookup:
df['To_Be_Filled'] = df.lookup(np.arange(len(df)), df['F'])
df
Out:
a b c d e F To_Be_Filled
0 0.02 0.62 0.31 0.67 0.27 a 0.02
1 0.30 0.07 0.23 0.42 0.00 a 0.30
2 0.82 0.59 0.34 0.73 0.29 a 0.82
3 0.90 0.80 0.13 0.14 0.07 d 0.14
4 0.50 0.62 0.94 0.34 0.53 d 0.34
5 0.59 0.84 0.95 0.42 0.54 d 0.42
6 0.13 0.33 0.87 0.20 0.25 d 0.20
7 0.47 0.37 0.84 0.69 0.28 e 0.28
np.arange(len(df)) can be replaced with df.index.
I have a probability table like this:
BC_array =[np.array(['B=n','B=m','B=s','B=n','B=m','B=s']),np.array(['C=F', 'C=F', 'C=F', 'C=T', 'C=T', 'C=T'])]
pD_BC_array=np.array([[0.9,0.8,0.1,0.3,0.4,0.01],[0.08,0.17,0.01,0.05,0.05,0.01],[0.01,0.01,0.87,0.05,0.15,0.97],[0.01,0.02,0.02,0.6,0.4,0.01]])
pD_BC=pd.DataFrame(pD_BC_array,index=['D=h','D=c','D=s','D=r'],columns=BC_array)
B=n B=m B=s B=n B=m B=s
C=F C=F C=F C=T C=T C=T
D=h 0.90 0.80 0.10 0.30 0.40 0.01
D=c 0.08 0.17 0.01 0.05 0.05 0.01
D=s 0.01 0.01 0.87 0.05 0.15 0.97
D=r 0.01 0.02 0.02 0.60 0.40 0.01
How could I marginalize 'C'(sum up all the 'C=F' and 'C=T' together) and get table:
B=n B=m B=s
D=h 1.20 1.20 0.11
D=c 0.13 0.22 0.02
D=s 0.06 0.16 1.84
D=r 0.61 0.42 0.03
like this?
You can call sum on the df and pass params axis=1 for row-wise and level=0 to sum along that level:
In [259]:
pD_BC.sum(axis=1, level=0)
Out[259]:
B=m B=n B=s
D=h 1.20 1.20 0.11
D=c 0.22 0.13 0.02
D=s 0.16 0.06 1.84
D=r 0.42 0.61 0.03
I have a python function that randomize a dictionary representing a position specific scoring matrix.
for example:
mat = {
'A' : [ 0.53, 0.66, 0.67, 0.05, 0.01, 0.86, 0.03, 0.97, 0.33, 0.41, 0.26 ]
'C' : [ 0.14, 0.04, 0.13, 0.92, 0.99, 0.04, 0.94, 0.00, 0.07, 0.23, 0.35 ]
'T' : [ 0.25, 0.07, 0.01, 0.01, 0.00, 0.04, 0.00, 0.03, 0.06, 0.12, 0.14 ]
'G' : [ 0.08, 0.23, 0.20, 0.02, 0.00, 0.06, 0.04, 0.00, 0.54, 0.24, 0.25 ]
}
The scambling function:
def scramble_matrix(matrix, iterations):
mat_len = len(matrix["A"])
pos1 = pos2 = 0
for count in range(iterations):
pos1,pos2 = random.sample(range(mat_len), 2)
#suffle the matrix:
for nuc in matrix.keys():
matrix[nuc][pos1],matrix[nuc][pos2] = matrix[nuc][pos2],matrix[nuc][pos1]
return matrix
def print_matrix(matrix):
for nuc in matrix.keys():
print nuc+"[",
for count in matrix[nuc]:
print "%.2f"%count,
print "]"
now to the problem...
When I try to scramble a matrix directly, It's works fine:
print_matrix(mat)
print ""
print_matrix(scramble_matrix(mat,10))
gives:
A[ 0.53 0.66 0.67 0.05 0.01 0.86 0.03 0.97 0.33 0.41 0.26 ]
C[ 0.14 0.04 0.13 0.92 0.99 0.04 0.94 0.00 0.07 0.23 0.35 ]
T[ 0.25 0.07 0.01 0.01 0.00 0.04 0.00 0.03 0.06 0.12 0.14 ]
G[ 0.08 0.23 0.20 0.02 0.00 0.06 0.04 0.00 0.54 0.24 0.25 ]
A[ 0.41 0.97 0.03 0.86 0.53 0.66 0.33.05 0.67 0.26 0.01 ]
C[ 0.23 0.00 0.94 0.04 0.14 0.04 0.07 0.92 0.13 0.35 0.99 ]
T[ 0.12 0.03 0.00 0.04 0.25 0.07 0.06 0.01 0.01 0.14 0.00 ]
G[ 0.24 0.00 0.04 0.06 0.08 0.23 0.54 0.02 0.20 0.25 0.00 ]
but when I try to assign this scrambling to a list , it does not work!!! ...
print_matrix(mat)
s=[]
for x in range(3):
s.append(scramble_matrix(mat,10))
for matrix in s:
print ""
print_matrix(matrix)
result:
A[ 0.53 0.66 0.67 0.05 0.01 0.86 0.03 0.97 0.33 0.41 0.26 ]
C[ 0.14 0.04 0.13 0.92 0.99 0.04 0.94 0.00 0.07 0.23 0.35 ]
T[ 0.25 0.07 0.01 0.01 0.00 0.04 0.00 0.03 0.06 0.12 0.14 ]
G[ 0.08 0.23 0.20 0.02 0.00 0.06 0.04 0.00 0.54 0.24 0.25 ]
A[ 0.01 0.66 0.97 0.67 0.03 0.05 0.33 0.53 0.26 0.41 0.86 ]
C[ 0.99 0.04 0.00 0.13 0.94 0.92 0.07 0.14 0.35 0.23 0.04 ]
T[ 0.00 0.07 0.03 0.01 0.00 0.01 0.06 0.25 0.14 0.12 0.04 ]
G[ 0.00 0.23 0.00 0.20 0.04 0.02 0.54 0.08 0.25 0.24 0.06 ]
A[ 0.01 0.66 0.97 0.67 0.03 0.05 0.33 0.53 0.26 0.41 0.86 ]
C[ 0.99 0.04 0.00 0.13 0.94 0.92 0.07 0.14 0.35 0.23 0.04 ]
T[ 0.00 0.07 0.03 0.01 0.00 0.01 0.06 0.25 0.14 0.12 0.04 ]
G[ 0.00 0.23 0.00 0.20 0.04 0.02 0.54 0.08 0.25 0.24 0.06 ]
A[ 0.01 0.66 0.97 0.67 0.03 0.05 0.33 0.53 0.26 0.41 0.86 ]
C[ 0.99 0.04 0.00 0.13 0.94 0.92 0.07 0.14 0.35 0.23 0.04 ]
T[ 0.00 0.07 0.03 0.01 0.00 0.01 0.06 0.25 0.14 0.12 0.04 ]
G[ 0.00 0.23 0.00 0.20 0.04 0.02 0.54 0.08 0.25 0.24 0.06 ]
What is the problem???
Why the scrambling do not work after the first time, and all the list filled with the same matrix?!
Your scrambling function is modifying the existing matrix, it is not creating a new one.
You create a matrix, scramble it and add it to a list. Then you scramble it again and add it again to the list. Both elements of the list contain now the same matrix object, which got scrambled twice.
You are shuffling the same matrix in-place for 3 times. But you really want to shuffle 3 copies of original matrix. So you should do:
from copy import deepcopy
print_matrix(mat)
s=[]
for x in range(3):
s.append(scramble_matrix(deepcopy(mat),10)) # note the deepcopy()
for matrix in s:
print ""
print_matrix(matrix)