R 如何确定字符向量是有效的数字向量还是整数向量

R 如何确定字符向量是有效的数字向量还是整数向量,r,lapply,rbind,R,Lapply,Rbind,我试图将嵌套列表结构转换为数据帧。该列表类似于以下内容(它是使用httr包从解析的JSON读取的序列化数据) 最后,我可以使用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

我试图将嵌套列表结构转换为数据帧。该列表类似于以下内容(它是使用httr包从解析的JSON读取的序列化数据)

最后,我可以使用
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
myDF如前所述,检查
As.numeric
是否返回
NA
值是检查字符串是否包含数字数据的简单方法。现在,您可以执行以下操作:

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

myDF2您可以使用
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

我不认为plyr::ldply比常规的base R方法有任何优势:

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

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

出现问题的原因是错误地试图“展平”数据,而不考虑其内在结构。

如果您只想转换所有在读入时被错误分类为字符的数值向量,您还可以使用
Hmisc
软件包中的函数
all.is.numeric

myDF2 <- lapply(myDF, Hmisc::all.is.numeric, what = "vector", extras = NA)
然后应用于data.frame:

myDF2 <- lapply(myDF, catchNumeric)

myDF2如果您有一个包含字符串的列表或向量,并且您只想将数字转换为数字,则可能的解决方案是:

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

catchNumeric当包含NAs时@josliber的函数将不起作用(尽管它很好地回答了示例数据的问题)@Amy M的功能应该可以工作,但需要加载
Hmisc

  myList <- list(object1 = list(w=1, x=list(y=0.1, z="cat")), object2 = list(w=NULL, x=list(z="dog")))
像这样的东西怎么样:

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)
}

can.be.numeric您可以使用
lappy(myList,as.data.frame)
创建“平面列表”,因为有一种方法
as.data.frame.list
<代码>取消列表
将您的“列表”转换为原子向量,所有内容都强制为“字符”是!我最喜欢这个
plyr::rbind.fill(lappy(myList,as.data.frame))
非常优雅!如果你回答我,我会接受的。我的示例数据太简单了。实际数据参差不齐,这意味着并非每个对象都存在所有变量。并且一些列表元素为空,这会在
data.frame()
中产生错误。我编辑了这个问题以包含更好的示例数据。@AndrewBarr:在这种情况下,请参见类似
lappy(myList,function(x)as.data.frame(unlist(x,FALSE)))的内容。
注意:我最终使用了这个解决方案。我添加的唯一一个想法是使用
as.data.frame(myDF2)
将其转换回数据帧,通过编写suppressWarnings(any)(is.na(as.numeric(as.character(col '))))))使长逻辑表达式稍微简单一点
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
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)
}