All Articles
    Search by

    Seuratをh5seuratに書き出して読み込むときのエラー

    Seuratオブジェクトを作成中に遭遇したエラーとその解決方法【Error in validObject: ‘counts’ must have the same cells as ‘data’】

    ❗ 結論

    Seuratオブジェクト作成時に以下のようなエラーが出た場合:

    Error in validObject(object = value): 
      invalid class “Assay” object: 'counts' must have the same cells as 'data'

    これは countsdata列名(細胞名)が一致していない ために起こります。

    そしてこの情報を揃えないと書き出せても読み込めないh5seuratが出来上がってしまいます。

    Seurat objectを書き出して保存する際、色々なフォーマットで保存することが可能だ。時にはScanpyにデータを移行しなければならない場面があるが、h5seurat形式はデータの損失も少なく、優れた形式の一つだ。

    seu = Read10X("/shared/oodake/sc-public-data/Autsornworawat2020/GSE151117/GSM4567001_ES1txp/")
    seu = CreateSeuratObject(counts = seu, project = "ES1txp")
    SaveH5Seurat(seu, "test1.h5seurat",overwrite = TRUE)

    ところがどっこい、これを読み込もうとするとエラーになるのである。

    ✅ 解決策(やることはこれだけ)

    # ポイント
    colnames(expr_mat) <- colnames(seurat_obj)
    
    # 新しい Assay オブジェクトを作成し、data も counts と同じに設定する
    new_assay <- CreateAssayObject(counts = expr_mat)
    new_assay@data <- new_assay@counts
    
    # 既存の Seurat オブジェクトの "RNA" アッセイを置き換える
    seu[["RNA"]] <- new_assay
    
    # h5seurat形式で書き出し(以下のコードではディレクトリが存在している前提です)
    SaveH5Seurat(seu, filename = "Augsorworawat2020/ES1txp.h5seurat", overwrite = TRUE)
    

    🧠 なぜこうなる?Seuratオブジェクトの構造と原因解説

    Seuratオブジェクトの内部はS4クラスで実装されており、以下のような構造を持っています。

    主な要素(スロット)

    • @assays$RNA@counts:生のカウントデータ(未処理)
    • @assays$RNA@data:正規化済みデータ(例:log1p-transformedなど)

    よくある原因

    h5seuratを読み込む際、dataを参照しに行くようです。

    • counts は細胞A, B, C の順なのに、data は A, C, B の順だった
    • data にしか含まれていない細胞、またはその逆があった
    • それぞれの列名が一致していない(例:プレフィックス付き・無し)

    なぜ名前が違うことがあるの?

    • Seuratのバージョン間の違い
    • 他ツールで整形されたデータ
    • counts, data, scale.data, raw.data など、使用状況によって異なる命名

    どうやって確認する?

    • オブジェクトのスロット名を確認:
      slotNames(seurat_obj)
    • 構造を確認:
      str(seurat_obj)
    • 特定のスロットを見る:
      colnames(seurat_obj@assays$RNA@counts)
      colnames(seurat_obj@assays$RNA@data)

    🔎 同じ問題で悩んでいた人たち

    このエラーはSeuratユーザーの間でよく出ているようです:

    📌 この問題の詳細 - Seurat オブジェクトについて

    Seuratオブジェクトは S4 クラスで実装されているため、内部の各要素(スロット)には @ 演算子でアクセスできます。

    例:

    生データ(raw counts):

    オブジェクト名@assays$RNA@counts

    正規化済みデータ(normalized data):

    オブジェクト名@assays$RNA@data

    🧭 要素名の命名について

    Seuratでは、以下のように要素名が状況に応じて命名されています:

    標準ケース(例:RNAシングルセル解析の場合)

    • "counts"
      → 生データ(カウント値)の格納場所
    • "data"
      → 正規化や対数変換など、解析用に加工されたデータ

    別のケース

    • 以前のバージョン(Seurat v2など)や、特定の処理後のオブジェクトでは
      • "raw.data" など、異なる名前が使われる場合もありました
    • ただし、v3以降は基本的に "counts""data" に統一されています

    ❓ なぜ名前が異なる場合があるのか?

    • Seuratのバージョンアップに伴い、内部構造や命名規則が改善・統一されました
    • レガシーなデータや、変換ツールを経由したオブジェクトの場合、以前の命名規則が残っていることがあります

    🧪 内部要素の確認方法

    要素名や内容が不明な場合、以下の方法で確認・検証できます:

    slotNames() 関数

    slotNames(オブジェクト名)

    → これでそのSeuratオブジェクトが持つ全てのスロット名が一覧で得られます

    str() 関数

    str(オブジェクト名)

    → オブジェクト全体の構造を詳細に確認可能


    このように、Seuratオブジェクトの各要素(例えば countsdata)は、その役割に応じた名前が付けられており、バージョンや処理の流れによっては異なる名称になることもあります。

    内部の中身が不明な場合は、slotNames()str() を利用して、現在のオブジェクトの構造や中身を把握することが解決の鍵となります。


    # シンプルなチェック関数
    check_alignment <- function(counts, data) {
      if (!identical(colnames(counts), colnames(data))) {
        warning("列名が一致していません")
      } else {
        message("OK: 列名は一致しています")
      }
    }

    ✍ おわりに

    Seuratは便利ですが、内部構造が複雑なので、こうした 「静かなる地雷」 に引っかかることがあります。今回のようにエラー文が示す構造を理解しておくと、次回から落ち着いて対応できるようになります。

    Published Mar 28, 2025

    © 2020-2024 Hiroyuki Odake