【问题标题】:How to add data to R data frame如何将数据添加到 R 数据框
【发布时间】:2014-07-30 19:21:40
【问题描述】:

我无法想象它会那么困难,但可能是来自 Python,我的心态是有偏见的。

我知道我要进行 50 次计算,每次计算的结果,连同表征计算的两个参数,应该建立一个数据框。

所以我的方法是实例化数据框,然后我想在结果可用时添加它们。请参阅下面指示的行:

# Number of simulations
nsim = 50

# The data frame which should carry the calculation (parameters and solutions).
sol <- data.frame(col.names=c("ni", "Xbar", "n"))

# Fifty values for n.
n <- seq.int(5, 5000, length.out=nsim)

for(ni in n)
{
    # A random sample containing possible duplicates.
    X <- sample(seq(-ni, ni, length=ni+1), replace=T)
    Xbar <- round(mean(X), 3)
    sol <- rbind(sol, c(ni, Xbar, n))  # <<-- How to do this correctly??
}   

这不起作用。

【问题讨论】:

    标签: r


    【解决方案1】:

    有两种方法可以正确地做到这一点。一种是预先定义你的 data.frame(它的大小),然后在 for 循环中迭代地填充它:

    nsim <- 10 # reduce to 10 to simplify output
    n <- seq.int(5, 5000, length.out=nsim)
    
    sol <- setNames(data.frame(matrix(nrow=nsim, ncol=3)), c("ni", "Xbar", "n"))
    
    set.seed(1) # for reproducibility
    for(ni in seq_along(n)) {
        Xbar <- round(mean(sample(seq(-n[ni], n[ni], length=n[ni]+1), replace=T)), 3)
        sol[ni,] <- c(ni, Xbar, n[ni])
    }   
    

    或者,您可以在 n 向量上使用 sapply 来创建结果向量,然后将 cbind 重新组合在一起:

    set.seed(1) # for reproducibility
    sol <- data.frame(
        ni = seq_along(n),
        Xbar = sapply(n, function(ni) {
            round(mean(sample(seq(-ni, ni, length=ni+1), replace=T)), 3)
        }),
        n = n
    )
    

    无论哪种方式,您都会得到一个不错的数据框:

    > str(sol)
    'data.frame':   10 obs. of  3 variables:
     $ ni  : num  1 2 3 4 5 6 7 8 9 10
     $ Xbar: num  0.667 -0.232 -14.599 -26.026 36.51 ...
     $ n   : num  5 560 1115 1670 2225 ...
    

    【讨论】:

    • @thelatemail 正确。固定的。以后可以随意在我的答案中编辑这类东西。 :)
    • 好的,所以我需要从一开始就用它的大小来实例化数据框。
    • @TMOTTM 你没有这样做,但是初始化和填充比重复rbind效率高很多倍,因为rbind会复制每次内存中的data.frame。
    【解决方案2】:

    1) 检查您最初的 sol 包含的内容。

    > sol <- data.frame(col.names=c("ni", "Xbar", "n"))
    > sol
      col.names
    1        ni
    2      Xbar
    3         n
    

    不是你想要的。见this question

    2) 确保seq.int 符合您的预期 - 检查seq.int 的文档(或只是其输出)。例如看看n 包含什么:

    > n
     [1]    5.0000  106.9388  208.8776  310.8163  412.7551  514.6939  616.6327
     [8]  718.5714  820.5102  922.4490 1024.3878 1126.3265 1228.2653 1330.2041
    [15] 1432.1429 1534.0816 1636.0204 1737.9592 1839.8980 1941.8367 2043.7755
    [22] 2145.7143 2247.6531 2349.5918 2451.5306 2553.4694 2655.4082 2757.3469
    [29] 2859.2857 2961.2245 3063.1633 3165.1020 3267.0408 3368.9796 3470.9184
    [36] 3572.8571 3674.7959 3776.7347 3878.6735 3980.6122 4082.5510 4184.4898
    [43] 4286.4286 4388.3673 4490.3061 4592.2449 4694.1837 4796.1224 4898.0612
    [50] 5000.0000
    

    这是你的意思吗?

    3) 给定 (1) 的问题并不奇怪,但无论如何,只需通过循环执行第一次,一次一行。看看会发生什么:

    sim = 50
    sol <- data.frame(col.names=c("ni", "Xbar", "n"))
    ni=5
    X <- sample(seq(-ni, ni, length=ni+1), replace=T)
    Xbar <- round(mean(X), 3)
    sol <- rbind(sol, c(ni, Xbar, n))  
    print(sol)
    

    给予:

    Warning message:
    In `[<-.factor`(`*tmp*`, ri, value = 5) :
      invalid factor level, NA generated
    >     print(sol)
      col.names
    1        ni
    2      Xbar
    3         n
    4      <NA>
    

    现在的行为并不令人惊讶;我们不能在一列中添加三列。

    4) 无论如何,您都不想这样做。最好将sol初始化为它的最终大小,然后填充。

    请参阅,例如,this answer

    然而,更常见的 R 习惯用法是尽可能避免循环;有许多函数可以让您一次创建整个事物。

    【讨论】:

    • 1-3) 我明白了。 4)问题的目的正是要学习如何“填写”。这是我的主要理解问题。
    • 3) 我假设通过定义col.names,我定义了列数,不是吗?
    • 你不是。您正在定义一个名为 col.names 的变量,这就是为什么您得到一列而不是 3 列的原因。data.frame 没有 col.names 参数。见?data.frame。我已在我的答案中添加了一个链接,以在您的第一条评论中澄清问题。
    • 你是对的,误读了?data.frame中的'row.names'参数。
    【解决方案3】:

    首先,您能否阐明您期望的预期输出格式? 截至目前,在修改代码以生成数据框时,将生成以下输出(如果这是您所期望的,请告诉我,然后生成以下内容并不难):

    ni       Xbar     n
    10.000   2.182   12.000
    

    如果这是您所期望的,那么执行此操作的一种方法如下:

    第 1 步:创建向量

    第 2 步:根据上述向量创建数据框

    第 3 步:循环运行您的操作并逐行填写。

    nsim=50
    n=seq.int(5, 5000, length.out=nsim)
    ni<-vector(mode='numeric',length=nsim)
    Xbar<-vector(mode='numeric',length=nsim)
    out<-data.frame(ni=ni,Xbar=Xbar,n=n)
    
    for ( i in 1:length(n)){
      X<- sample(seq(-n[i], n[i], length=n[i]+1), replace=T)
      out[i,'Xbar'] <- round(mean(X), 3)
      out[i,'ni']<-n[i]
    }
    

    输出如下:

    【讨论】:

      猜你喜欢
      • 2020-10-19
      • 2020-08-02
      • 1970-01-01
      • 1970-01-01
      • 2015-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-29
      相关资源
      最近更新 更多