如何从(空)向量构建数据框?

How to build a dataframe from an (empty) vector?

下面的代码片段将一对向量转换为一个数据框,沿途填充一列以指示出处 ("State"),另一列以指示类型 ("Ingredient") .

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 <- setdiff(c(11, 13, 17), c(11, 13, 17)).

如何在处理空向量的情况下从向量构建数据框?携带 "data frame is empty" 标志的选项将是一个糟糕的选择,因为代码会充满 if 语句。

更新

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

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

使用 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