Skip to content

Commit 9bdd700

Browse files
authored
Merge pull request #181 from dpeerlab/dominik/pandas3-cow-fix-issue180
Dominik/pandas3 cow fix issue180
2 parents dbcc349 + ee1dd45 commit 9bdd700

3 files changed

Lines changed: 16 additions & 5 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ Release Notes
7474
-------------
7575

7676
### Version 1.4.5 (future)
77+
* Fix: pandas 3 compatibility. Under pandas 3 (mandatory Copy-on-Write) `DataFrame.values` returns a read-only view, so several in-place mutations raised `ValueError: assignment destination is read-only`. `run_palantir` failed in `_differentiation_entropy` (terminal-state identity block, now built with `np.eye(...)`), and `select_branch_cells` failed on its NaN fill of the fate-probability array (now copied before mutation). Compatible with both pandas 2 and 3 ([#180](https://github.com/dpeerlab/Palantir/issues/180)).
7778
* Use `numpy.random.Generator` in place of the legacy global `numpy.random.RandomState` and require
7879
`numpy>=1.17`. Note that since the default PRNG is now [PCG64](https://numpy.org/devdocs/reference/random/bit_generators/pcg64.html) instead of the Mersenne Twister, numerical outputs are expected to differ from
7980
those in previous versions. If exact reproducibility is required, users should pin the relevant prior version.

src/palantir/core.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -713,8 +713,11 @@ def _differentiation_entropy(
713713
Q = T[trans_states, :][:, trans_states]
714714
if len(trans_states) == 0:
715715
ent = pd.Series(0, index=terminal_states)
716-
bp = pd.DataFrame(0, index=terminal_states, columns=terminal_states)
717-
bp.values[range(len(terminal_states)), range(len(terminal_states))] = 1
716+
bp = pd.DataFrame(
717+
np.eye(len(terminal_states)),
718+
index=terminal_states,
719+
columns=terminal_states,
720+
)
718721
return ent, bp
719722

720723
# Fundamental matrix solver
@@ -761,8 +764,11 @@ def _differentiation_entropy(
761764

762765
# Add terminal states
763766
ent = pd.concat([ent, pd.Series(0, index=terminal_states)])
764-
bp = pd.DataFrame(0, index=terminal_states, columns=terminal_states)
765-
bp.values[range(len(terminal_states)), range(len(terminal_states))] = 1
767+
bp = pd.DataFrame(
768+
np.eye(len(terminal_states)),
769+
index=terminal_states,
770+
columns=terminal_states,
771+
)
766772
branch_probs = pd.concat([branch_probs, bp.loc[:, branch_probs.columns]])
767773

768774
return ent, branch_probs

src/palantir/presults.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ def cluster_gene_trends(
528528
columns=trends.columns,
529529
)
530530

531-
gt_ad = AnnData(trends.values, dtype=np.float32)
531+
gt_ad = AnnData(trends.values.astype(np.float32))
532532
sc.pp.neighbors(gt_ad, n_neighbors=n_neighbors, use_rep="X")
533533

534534
# Add required kwargs for leiden with igraph backend to avoid FutureWarning
@@ -604,6 +604,10 @@ def select_branch_cells(
604604
fate_probs, fate_names = _validate_obsm_key(ad, fate_prob_key, as_df=False)
605605
pseudotime = ad.obs[pseudo_time_key].values
606606

607+
# Own the array before the in-place NaN fill: when obsm holds a DataFrame,
608+
# _validate_obsm_key returns a .values view that is read-only under pandas 3
609+
# (mandatory Copy-on-Write).
610+
fate_probs = fate_probs.copy()
607611
fate_probs[np.isnan(fate_probs)] = 1 / fate_probs.shape[1]
608612

609613
idx = np.argsort(pseudotime)

0 commit comments

Comments
 (0)