web-dev-qa-db-ja.com

文字ベクトルが有効な数値または整数ベクトルであるかどうかを判断する方法

ネストされたリスト構造をデータフレームに変換しようとしています。リストは次のようになります(httrパッケージを使用して読み込まれた解析済みJSONからのシリアル化されたデータです)。

_  myList <- list(object1 = list(w=1, x=list(y=0.1, z="cat")), object2 = list(w=NULL, x=list(z="dog")))
_

編集:元のサンプルデータは単純すぎました。実際のデータは不揃いです。つまり、すべてのオブジェクトにすべての変数が存在するわけではなく、リスト要素の一部がNULLです。これを反映するようにデータを編集しました。

unlist(myList)は、リストを再帰的にフラット化する優れた機能を果たします。その後、lapplyを使用して、すべてのオブジェクトを適切にフラット化できます。

_  flatList <- lapply(myList, FUN= function(object) {return(as.data.frame(rbind(unlist(object))))}) 
_

最後に、_plyr::rbind.fill_を使用してボタンを押します。

_  myDF <- do.call(plyr::rbind.fill, flatList)
  str(myDF)

  #'data.frame':    2 obs. of  3 variables:
  #$ w  : Factor w/ 2 levels "1","2": 1 2
  #$ x.y: Factor w/ 2 levels "0.1","0.2": 1 2
  #$ x.z: Factor w/ 2 levels "cat","dog": 1 2
_

問題は、wとx.yが文字ベクトルとして解釈され、デフォルトでデータフレーム内の要素として解析されることです。 unlist()が原因だと思いますが、リスト構造を再帰的にフラット化する別の方法を見つけることはできません。回避策は、データフレームを後処理し、データ型を割り当てることです。ベクトルが有効な数値または整数のベクトルであるかどうかを判断するための最良の方法は何ですか?

18
Andrew Barr

説明したように ここas.numericNA値を返します。これは、文字列に数値データが含まれているかどうかを確認するための簡単な方法です。今、あなたは次のようなことをすることができます:

myDF2 <- lapply(myDF, function(col) {
  if (suppressWarnings(all(!is.na(as.numeric(as.character(col)))))) {
    as.numeric(as.character(col))
  } else {
    col
  }
})
str(myDF2)
# List of 3
#  $ w  : num [1:2] 1 2
#  $ x.y: num [1:2] 0.1 0.2
#  $ x.z: Factor w/ 2 levels "cat","dog": 1 2
15
josliber

NAが含まれている場合、@ josliberの関数は機能しません(サンプルデータの質問にはうまく答えますが)。 @Amy Mの関数は機能するはずですが、Hmiscパッケージをロードする必要があります。

このようなものはどうですか?

_can.be.numeric <- function(x) {
    stopifnot(is.atomic(x) || is.list(x)) # check if x is a vector
    numNAs <- sum(is.na(x))
    numNAs_new <- suppressWarnings(sum(is.na(as.numeric(x))))
    return(numNAs_new == numNAs)
}
_

入力ベクトルのNAsとas.numeric()の出力のNAsをカウントし、ベクトルをTRUEに「安全に」変換できる場合(つまり、numeric値を追加せずに)、NAを返します。

5
Stefan Avey

plyr::ldplyを使用できます:

ldply(myList,.fun=function(x)data.frame(x))

      .id w x.y x.z
1 object1 1 0.1 cat
2 object2 2 0.2 dog
1
agstudy

通常のベースRメソッドに対するplyr :: ldplyの利点はわかりません。

 do.call(rbind, lapply(myList, data.frame) )
#-------------

        w x.y x.z
object1 1 0.1 cat
object2 2 0.2 dog

この問題は、データの固有の構造を考慮せずにデータを「フラット化」しようとする誤った試みが原因で発生していました。

1
42-

文字列を含むリストまたはベクトルがあり、数値のみを数値に変換する場合、考えられる解決策は次のとおりです。

catchNumeric <- function(mylist) {
  newlist <- suppressWarnings(as.numeric(mylist))
  mylist <- as.list(mylist)
  mylist[!is.na(newlist)] <- newlist[!is.na(newlist)]
  mylist
}

> catchNumeric(c("123", "c12", "abc", "123.12"))
[[1]]
[1] 123

[[2]]
[1] "c12"

[[3]]
[1] "abc"

[[4]]
[1] 123.12

> catchNumeric(list("123", "c12", "abc", "123.12"))
[[1]]
[1] 123

[[2]]
[1] "c12"

[[3]]
[1] "abc"

[[4]]
[1] 123.12
0
Adriano Rivolli

読み込まれたときに誤って文字として分類されたすべての数値ベクトルを変換するだけの場合は、Hmiscパッケージの関数all.is.numericを使用することもできます。

myDF2 <- lapply(myDF, Hmisc::all.is.numeric, what = "vector", extras = NA)

what = "vector"を選択すると、ベクターに数値のみが含まれている場合は、ベクターが数値に変換されます。 NAまたはその他のタイプの欠落値は、上記のextras引数で指定されていない限り、変換を妨げます。

ただし、DateまたはPOSIXctベクトルを含むdata.frame全体に適用した場合、これらも数値に変換されることに注意してください。これを防ぐには、次のような関数でラップします。

catchNumeric <- function(dtcol) {
  require(Hmisc)
  if (is.character(dtcol)) {
    dtcol1 = all.is.numeric(dtcol, what = "vector", extras = NA)
  } else {
    dtcol1 = dtcol
  }
  return(dtcol1)
}

次に、data.frameに適用します。

myDF2 <- lapply(myDF, catchNumeric)
0
Amy M