erdogant / pca

pca: A Python Package for Principal Component Analysis.
https://erdogant.github.io/pca
MIT License
284 stars 42 forks source link

If y_continuous_cmap set to True, use continuous cmap in plot #19

Closed nightvision04 closed 2 years ago

nightvision04 commented 2 years ago

Could I create a PR for mapping y to a continuous color map? I was thinking syntax could be like this:

ax = model.biplot3d(n_feat=10, legend=False, y_continuous_cmap=True)

And it could generate something like the right side (in terms of the point colors).

image

erdogant commented 2 years ago

Sounds like a great idea! The cmap functionality already contains the possibility to reverse the color by adding "_r". My suggestion would be to add "_c" or so for a continuous cmap. What do you think?

Example:

cmap='Set1' # Normal
cmap='Set1_r' # To reverse
cmap='Set1_c' # Your implementation?
nightvision04 commented 2 years ago

I like your suggestion, however I think I prefer to make this behavior explicit. I'm concerned that we'll need to make a large section in the docstring section to explain each suffix . This might become confusing for some users.

erdogant commented 2 years ago

maybe yes. Do you have a suggestion to make the name y_continuous_cmap a bit shorter? It is kind of long and attractive for typos. What about: cmap_gradient or cmap_with_gradient.

nightvision04 commented 2 years ago

I really like cmap_gradient. It's elegant. Let's go with that?

erdogant commented 2 years ago

👍🏻

erdogant commented 2 years ago

I created an update with this functionality using the gradient parameter. Update to version >= 1.7.0

pip install -U pca

Example:

import numpy as np
from sklearn.datasets import load_iris

# Load dataset
X = pd.DataFrame(data=load_iris().data, columns=load_iris().feature_names, index=load_iris().target)
# X.reset_index(drop=True, inplace=True)

# Load pca
from pca import pca
model = pca(n_components=0.95)
model = pca(n_components=3)
results = model.fit_transform(X)
model.scatter(gradient='#ffffff')
model.scatter(gradient='#ffffff', cmap='Set2')
Benfeitas commented 1 year ago

Hi @erdogant , thanks for this. I'm trying to do a continuous gradient between all 3 classes (0, 1 and 2). Slightly adapting your example above I get:

import numpy as np
from sklearn.datasets import load_iris

# Load dataset
X = pd.DataFrame(data=load_iris().data, columns=load_iris().feature_names, index=load_iris().target)

# Load pca
from pca import pca
model = pca(n_components=0.95)
model = pca(n_components=3)
results = model.fit_transform(X, verbose=2)
model.scatter(gradient='#5dfa02', cmap='tab20',figsize=(6,6))

image

I understand that the gradient imposed basically highlights the centroids in each class. However, is it possible to do a continuous gradient between all three classes? An example to highlight the gradient (based on PC1):

import matplotlib 

df=results['PC']
fig,ax=plt.subplots()

g = ax.scatter(df['PC1'],df['PC2'], c=df['PC1'], s=30)
mappable = ax.collections[0]
fig.colorbar(mappable=mappable)

image

or based on class label

df['class']=df.index
fig,ax=plt.subplots()

g = ax.scatter(df['PC1'],df['PC2'], c=df['class'], s=30)
mappable = ax.collections[0]
fig.colorbar(mappable=mappable)

image

erdogant commented 1 year ago

I created some changes. Can you update the scatterdlibrary and try again? pip install -U scatterd

model.scatter(gradient='#5dfa02', cmap='tab20') image

You need to set all the classlabels the same. This can be done with y and set them all the same. model.scatter(gradient='#5dfa02', cmap='tab20', y=np.ones_like(model.results['PC'].index.values)) image