0
$\begingroup$

I have a tricky data set with cells that will have a higher percent of mitochondria genes than "typical" data sets. I would like to look at the mito percentage in each cluster without any filtering (e.g., subset(seurat_object, subset = nFeature_RNA > 200 & nFeature_RNA < 3000 & percent.mito < 10))

FeaturePlot(seurat_object, features=c('percent.mito'), cols = c("gold", "firebrick4"), pt.size=0.5, label=TRUE, repel=TRUE)

Done!

I would also like to calculate the average percent.mito for each cluster and place the value on the FeaturePlot/TSNE plots. I have no idea how to manipulate a Seurat object to calculate these values but I can probably figure out how to place those values on the graph -- probably with geom_text.

My Hail Mary approach is below:

p3 <- FeaturePlot(seurat_object, features=c('percent.mito'), cols = c("gold", "firebrick4"), pt.size=0.5, label=TRUE, repel=TRUE)
p3 <- lapply(X = p3, FUN = function(x) mean(p3))
CombinePlots(plots = p3)

My attempts yield the error below; I don't know if my approach is close to correct and therefore, I have spent little time working through the error message.

In mean.default(p3) : argument is not numeric or logical: returning NA
Execution halted

and

p3 <- FeaturePlot(seurat_object, features=c('percent.mito'), cols = c("gold", "firebrick4"), pt.size=0.5, label=TRUE, repel=TRUE)
p3 <- lapply(X = p3, FUN = function(x) mean(seurat_object$meta.data$seurat_clusters))
CombinePlots(plots = p3)
Error in `[[.Seurat`(x, i, drop = TRUE) :
  Cannot find 'meta.data' in this Seurat object
Calls: lapply ... lapply -> FUN -> mean -> $ -> $.Seurat -> [[ -> [[.Seurat

and

p3 <- FeaturePlot(seurat_object, features=c('percent.mito'), cols = c("gold", "firebrick4"), pt.size=0.5, label=TRUE, repel=TRUE)
p3 <- lapply(X = seurat_object, FUN = function(x) mean(seurat_object$meta.data$seurat_clusters))
CombinePlots(plots = p3)
Error in as.list.default(X) : 
  no method for coercing this S4 class to a vector
Calls: lapply -> lapply -> as.list -> as.list.default```

If anyone can provide some guidance -- you will be inducted into my personal hall of fame. :)

Thank you for your time.

P.S. I am using Seurat 3.1

Update:

md = surate_object@meta.data 
md_mean <- ddply(md, .(seurat_clusters), summarize, mean_mito_per=mean(percent.mito))

This was not the approach I was hoping for but I have the values -- which when expanded to the length of the original df, I can insert it into a free slot in the seurat_object.

If anyone has a better approach I would love to hear it.

UPDATE: Using @PPK's approach

# First the cluster annotation and the tsne embeddings are merged
label.df <- cbind(as.data.frame(seurat_object@meta.data), as.data.frame(seurat_object@reductions$tsne@cell.embeddings)) 

# using dplyr across to calculate the mean mitochondrial percentage and 
# the median tsne values per cluster
label.df <- label.df %>% dplyr::group_by(seurat_clusters) %>% dplyr::summarise(dplyr::across(percent.mito, ~ mean(.), .names = "mean_{.col}"), dplyr::across(contains("tSNE"), ~ median(.)))

# running FeaturePlot and adding the label layer
FeaturePlot(seurat_object, reduction = "tsne", features = "percent.mito") + 
  geom_text(data = label.df, aes(x = tSNE_1, y = tSNE_2, label = mean_percent.mito))

Error:

* object '.col' is a function.
ℹ Input `..1` is `dplyr::across(percent.mito, ~mean(.), .names = "mean_{.col}")`.
ℹ The error occured in group 1: seurat_clusters = "0".
Backtrace:
     █
  1. └─global::initial_clustering(BM0H, "BM0H")
  2.   └─`%>%`(...)
  3.     ├─base::withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
  4.     └─base::eval(quote(`_fseq`(`_lhs`)), env, env)
  5.       └─base::eval(quote(`_fseq`(`_lhs`)), env, env)
  6.         └─`_fseq`(`_lhs`)
  7.           └─magrittr::freduce(value, `_function_list`)
  8.             ├─base::withVisible(function_list[[k]](value))
  9.             └─function_list[[k]](value)
 10.               ├─dplyr::summarise(...)
 11.               └
$\endgroup$
2
$\begingroup$

You can extract the necessary values and add them directly the plot as a second layer using plot + geom_text(). This is very similar to the inner workings of the DimPlot function with label = TRUE but allows you to use anything as label.

# I use dplyr v1.0.2 for all data frame manipulations 
# First the cluster annotation and the tsne embeddings are merged
label.df <- cbind(as.data.frame(seurat_object@meta.data), as.data.frame(seurat_object@reductions$tsne@cell.embeddings)) 

# using dplyr across to calculate the mean mitochondrial percentage and 
# the median tsne values per cluster
label.df <- label.df %>% dplyr::group_by(seurat_clusters) %>% dplyr::summarise(dplyr::across(percent.mito, ~ mean(.), .names = "mean_{.col}"), dplyr::across(contains("tSNE"), ~ median(.)))

# running FeaturePlot and adding the label layer
FeaturePlot(seurat_object, reduction = "tsne", features = "percent.mito") + 
  geom_text(data = label.df, aes(x = tSNE_1, y = tSNE_2, label = mean_percent.mito))

The labels are positioned at the median position of the cells of a cluster. Typing LabelClusters (without brackets) in the R console will show you the labeling function used by Seurat that contains some additional ways of positioning the labels.
If you want to avoid overlapping labels you can use geom_text_repel from the ggrepel package.

$\endgroup$
9
  • $\begingroup$ I think this is exactly what I need @PPK. As the code is written, I get the following error: Error: unexpected ',' in: label.df <- label.df %>% group_by(seurat_clusters) %>% summarise(across(percent.mito, ~ mean(.), .names = "mean_{.col}"))," Execution halted. I believe summarise should hold both of the across items??? I have tinkered with it at bit, but have yet to resolve the error. $\endgroup$
    – cer
    Oct 27 '20 at 15:37
  • $\begingroup$ label.df <- label.df %>% group_by(seurat_clusters) %>% summarise(across(percent.mito, ~ mean(.), .names = "mean_{.col}"), across(contains(" tSNE"), ~ median(.))) Yields this error: Error: across()` must only be used inside dplyr verbs.` ... └─dplyr::across(percent.mito, ~mean(.), .names = "mean_{.col}")` -- any tips? $\endgroup$
    – cer
    Oct 27 '20 at 15:42
  • $\begingroup$ Sorry for the typo in the answer. As you correctly determined the summarise function was closed too early. I modified the answer accordingly. $\endgroup$
    – PPK
    Oct 27 '20 at 16:44
  • $\begingroup$ The second problem seems to be with some other package you are using overwriting some dplyr function. This happens pretty frequently because the functions have such generic names. I updated the answer with explicit calls to dplyr::group:by, dplyr::summarise and dplyr::across to circumvent this kind of problem. Hope this helps $\endgroup$
    – PPK
    Oct 27 '20 at 16:48
  • $\begingroup$ There is still some issue. I will post the error at the end of my post to preserve the format. $\endgroup$
    – cer
    Oct 27 '20 at 21:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.