【问题标题】:Create data frame by iteratively adding rows通过迭代添加行来创建数据框
【发布时间】:2017-07-27 16:32:38
【问题描述】:

我正在尝试创建一个数据框 (BOS.df),以便探索我将在接收实际数据之前执行的未来分析的结构。在这种情况下,假设有 4 家餐厅希望投放广告活动(“餐厅”变量)。活动将持续的总天数是 cmp.lngth。我想要他们为广告计费的随机数(ra.num)。广告活动从 StartDate 开始。最终,我想为每个餐厅的循环创建一个数据框,并通过添加行来为广告活动的每一天添加一个随机帐单号码。

#Create Data Placeholders
set.seed(123)
Restaurant <- c('B1', 'B2', 'B3', 'B4')
cmp.lngth <- 42
ra.num <- rnorm(cmp.lngth, mean = 100, sd = 10)
StartDate <- as.Date("2017-07-14")


BOS.df <- data.frame(matrix(NA, nrow =0, ncol = 3))
colnames(BOS.df) <- c("Restaurant", "Billings", "Date")


for(i in 1:length(Restaurant)){
  for(z in 1:cmp.lngth){
    BOS.row <- c(as.character(Restaurant[i]),ra.num[z],StartDate + 
    cmp.lngth[z]-1)
    BOS.df <- rbind(BOS.df, BOS.row)
  }
}

我的代码现在无法正常运行。列名不正确,如果根本没有正确放置数据。输出如下:

  X.B1. X.94.3952435344779. X.17402.
1    B1    94.3952435344779    17402
2    B1                <NA>     <NA>
3    B1                <NA>     <NA>
4    B1                <NA>     <NA>
5    B1                <NA>     <NA>
6    B1                <NA>     <NA>

如何获得正确的输出?有没有比使用 for 循环更有效的方法?

【问题讨论】:

  • lenght(Restuarant) 中的拼写错误无济于事。而cmp.lngth[z] 毫无意义,因为cmp.lngth 是一个数字,而不是一个向量——你可能只想在这里z
  • 嘿,安德鲁。感谢您的反馈。拼写错误来自我将代码翻译成我提交的内容,因此无法远程识别。

标签: r dataframe simulation


【解决方案1】:

使用expand.grid

cmp.lngth <- 2
StartDate <- as.Date("2017-07-14")

set.seed(1)
df1 <- data.frame(expand.grid(Restaurant, seq(cmp.lngth) + StartDate))
colnames(df1) <- c("Restaurant", "Date")
df1$Billings <- rnorm(nrow(df1), mean = 100, sd = 10)
df1 <- df1[ order(df1$Restaurant, df1$Date), ]

df1
#   Restaurant       Date  Billings
# 1         B1 2017-07-15  93.73546
# 5         B1 2017-07-16 103.29508
# 2         B2 2017-07-15 101.83643
# 6         B2 2017-07-16  91.79532
# 3         B3 2017-07-15  91.64371
# 7         B3 2017-07-16 104.87429
# 4         B4 2017-07-15 115.95281
# 8         B4 2017-07-16 107.38325

【讨论】:

  • 谢谢!我收到一条错误消息,但我仍然得到我想要的输出。错误:Error in order(NULL, c(17362, 17362, 17362, 17362, 17363, 17363, 17363, : argument 1 is not a vector
  • 对我来说很好。从错误中,我会在运行代码之前检查对象 Restaurant 的类。您也可以通过命名 expand.grid() 中的变量来简化它并摆脱对 data.frame 的调用:df1 &lt;- expand.grid(Restaurant = Restaurant, Date = seq(cmp.lngth) + StartDate)
  • 谢谢,ati​​retoo!我经历并合并了这些更改。我还检查了餐厅的类别并将其从字符转换为因子。
【解决方案2】:

您可以使用 rbind,但这是另一种方法。
此外,数据帧的长度应该是 cmp.lngth*length(Restaurant),而不是 cmp.lngth。

#Create Data Placeholders
set.seed(123)
Restaurant <- c('B1', 'B2', 'B3', 'B4')
cmp.lngth <- 42
ra.num <- rnorm(cmp.lngth, mean = 100, sd = 10)
StartDate <- as.Date("2017-07-14")


BOS.df <- data.frame(matrix(NA, nrow = cmp.lngth*length(Restaurant), ncol = 3))
colnames(BOS.df) <- c("Restaurant", "Billings", "Date")

count <- 1
for(name in Restaurant){
    for(z in 1:cmp.lngth){
        BOS.row <- c(name, ra.num[z], as.character(StartDate + z - 1))
        BOS.df[count,] <- BOS.row
        count <- count + 1
    }
}

我还建议您查看名为 tidyverse 的包,并使用带有 tibble 的 add_row 而不是数据框。这是一个示例代码:

library(tidyverse)
BOS.tb <- tibble(Restaurant = character(),
                 Billings = numeric(),
                 Date = character())

for(name in Restaurant){
    for(z in 1:cmp.lngth){
        BOS.row <- c(name, ra.num[z], as.character(StartDate + z - 1))
        BOS.tb <- add_row(BOS.tb, 
                          Restaurant = name, 
                          Billings = ra.num[z], 
                          Date = as.character(StartDate + z - 1))
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-08
    • 1970-01-01
    • 2017-06-15
    • 2019-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多