如何从(空)向量构建数据框?
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
效果很好。至少最初。但是插入一列仍然存在问题。如果 overflow
和 underflow
都是空列表,则 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_frame
和dplyr::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
另一位已删除评论的评论者指出,您可以将 rep
与 times = length(x)
一起使用,其中 x
是 overflow
或 underflow
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
下面的代码片段将一对向量转换为一个数据框,沿途填充一列以指示出处 ("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
效果很好。至少最初。但是插入一列仍然存在问题。如果 overflow
和 underflow
都是空列表,则 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_frame
和dplyr::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
另一位已删除评论的评论者指出,您可以将 rep
与 times = length(x)
一起使用,其中 x
是 overflow
或 underflow
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