【问题标题】:How to build a dataframe from an (empty) vector?如何从(空)向量构建数据框?
【发布时间】:2018-08-16 17:38:47
【问题描述】:

下面的代码 sn-p 将一对向量转换为一个数据框,沿途填充一列表示出处(“状态”),另一列表示类型(“成分”)。

overflow  <- setdiff(c(21, 23, 27), c(21, 23))
underflow <- setdiff(c(11, 13, 17), c(17))

dfo <- data.frame("State"="over", Value=overflow)
dfu <- data.frame("State"="under", Value=underflow)
df <- rbind(dfo, dfu)

df$Ingredient <- "Beans"

有了给定的数据,一切都很好。我们得到以下数据框。

> df
  State Value Ingredient
1  over    27      Beans
2 under    11      Beans
3 under    13      Beans

但这对于setdiff 产生空向量时的边界情况还不够好(例如:underflow &lt;- setdiff(c(11, 13, 17), c(11, 13, 17))

在处理空向量的情况下,如何从向量构建数据框?携带“数据框为空”标志的选项将是一个糟糕的选项,因为代码中会充斥着if 语句。

更新

代替对@AndS. 建议的评论:

dplyr::data_frame 替换data.frame 效果很好。至少最初。但是插入一列仍然存在问题。如果overflowunderflow 都是空列表,则df$Ingredient &lt;- "Beans" 失败。

【问题讨论】:

  • 尝试dplyr::data_frame 而不是data.frame 这将使观察数据帧为零而不是引发错误。
  • 使用library(data.table),你可以初始化一些东西dt &lt;- data.table(State = character(), Value = numeric(), Ingredient = character())工作正常。或者,空的 data.table 将从您上面列出的参数继承名称,因为 R 对象类型被传递。
  • @AndS。您的解决方案几乎可以工作。我更新了问题。
  • 没问题,坚持使用 dplyr,而不是 df$Ingredient &lt;- "Beans",在 mutate 中分配变量。例如:df &lt;- rbind(dfo, dfu) %&gt;% mutate(Ingredient = "Beans") 这仍然会使您成为零观察数据框,但现在有一个额外的列并且没有错误。如果有任何观察,“beans”将被添加到新列中。

标签: r dataframe vector empty-list


【解决方案1】:

使用dplyr::data_frame 可能是最好的选择,但这里有一个基本的 R 方法,只是为了好玩

flow <- list(over  = setdiff(c(21, 23, 27), c(21, 23)),
             under = setdiff(c(11, 13, 17), c(17)))


flow.df <- Map(function(State, x) 
                if(length(x)) data.frame(State, x, Ingredient = 'Beans')
               , names(flow)
               , flow)

df <- do.call(rbind, flow.df)

df

#         State  x Ingredient
# over     over 27      Beans
# under.1 under 11      Beans
# under.2 under 13      Beans

当其中一个为空时:

flow <- list(over  = setdiff(c(21, 23, 21), c(21, 23)),
             under = setdiff(c(11, 13, 17), c(17)))


flow.df <- Map(function(State, x) 
                if(length(x)) data.frame(State, x, Ingredient = 'Beans')
               , names(flow)
               , flow)

df <- do.call(rbind, flow.df)

df

#         State  x Ingredient
# under.1 under 11      Beans
# under.2 under 13      Beans

按照@AndS 的建议使用dplyr::data_framedplyr::mutate。让你避免if 声明:

library(dplyr)

flow <- list(over  = setdiff(c(21, 23, 21), c(21, 23)),
             under = setdiff(c(11, 13, 17), c(17)))


flow.df <- Map(function(State, x) data_frame(State, x)
               , names(flow)
               , flow)

df <- do.call(rbind, flow.df)

df %>% mutate(Ingredient = 'Beans')

# # A tibble: 2 x 3
#   State     x Ingredient
# * <chr> <dbl> <chr>     
# 1 under  11.0 Beans     
# 2 under  13.0 Beans   

另一位已删除评论的评论者指出,您可以将reptimes = length(x) 一起使用,其中xoverflowunderflow

flow <- list(over  = setdiff(c(21, 23, 21), c(21, 23)),
             under = setdiff(c(11, 13, 17), c(17)))


flow.df <- Map(function(State, x, len) 
                data.frame(State = rep(State, len)
                           , x
                           , Ingredient = rep('Beans', len))
               , names(flow)
               , flow
               , lengths(flow))

df <- do.call(rbind, flow.df)

df

#         State  x Ingredient
# under.1 under 11      Beans
# under.2 under 13      Beans

【讨论】:

  • 嘿@Ryan,为了完整起见,您要加入data_frame 示例吗?
  • @Ryan 所有不错的建议。 dplyr 是最干净的,但是您删除了仍然有问题的部分(将列添加到空的 data_frame)。我更新了问题。
猜你喜欢
  • 1970-01-01
  • 2017-12-10
  • 2021-07-11
  • 1970-01-01
  • 2019-08-06
  • 2020-01-16
  • 1970-01-01
  • 2021-10-13
  • 1970-01-01
相关资源
最近更新 更多