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

时间:2018-08-16 17:38:47

标签: r dataframe vector empty-list

下面的代码段将一对向量转换为数据帧,并沿一列填充以指示出处(“状态”),另一列填充以指示类型(“成分”)。

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)))的边界情况,这还不够好。

在处理空向量的情况下,如何从向量构建数据帧?带有“数据框为空”标志的选项将是一个不好的选择,因为该代码将充满if语句。

更新

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

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

1 个答案:

答案 0 :(得分: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