如何将任意序列附加到数据框列

时间:2018-08-14 13:28:39

标签: r

我试图在这样的for循环中将值添加到数据框-

z <- data.frame()
rnms <- rownames(prevdata)
for (i in 1:nrow(prevdata)) {
    s <- stack(prevdata[i, ])
    # Here, the names of the second and third columns are 'ind' and 'values' even though I've specified the column names... idk why.
    z <- rbind(z, data.frame(year=rnms[i], month=s[2], values=s[1])) 
    # Get months remaining.
    tmp <- nrow(s)+1 
    # try to assign the data for missing months as zero. 
    # This fails and assigns NA to the remaining months instead of the values from tmp to 12.   
    z <- rbind(z, data.frame(year=rnms[i], ind=seq(tmp:12) + tmp - 1, values=0)) 
}                             Doesn't work ^^^^^^^^^^^^^^^^^^^^^^^^^
colnames(z) <- c("YEAR", "MONTH", "values")

我不明白为什么这行不通。

执行seq(tmp:12)而不是seq(tmp:12) + tmp - 1是可行的,但是会导致分配的范围是1到tmp,而不是tmp到12的范围。 这是prevdata的示例-

>head(prevdata)
         1     2     3     4     5     6     7
1963  74.1 155.2 226.4 186.7  37.2  23.6  23.6
1964 135.3 204.9 180.6 223.4 186.0 111.6 127.0
1965  69.3  24.2 151.9 321.3 121.7 147.8  44.1
1966  21.1 125.7  62.1 109.8 101.3  68.0 123.9
1967  12.4 118.0 245.4 269.6 139.1 117.1  63.1
1968  69.8  37.2 264.8 112.8 133.5  24.2  62.3

使用ind=seq(tmp:12) + tmp - 1会得到-

> z[1:12,]
   year  ind values
1  1963    1   74.1
2  1963    2  155.2
3  1963    3  226.4
4  1963    4  186.7
5  1963    5   37.2
6  1963    6   23.6
7  1963    7   23.6
8  1963 <NA>    0.0 < ind here should be 8, 9, 10...
9  1963 <NA>    0.0
10 1963 <NA>    0.0
11 1963 <NA>    0.0
12 1963 <NA>    0.0

使用ind=seq(tmp:12)会得到-

> z[1:12,]
   year  ind values
1  1963    1   74.1
2  1963    2  155.2
3  1963    3  226.4
4  1963    4  186.7
5  1963    5   37.2
6  1963    6   23.6
7  1963    7   23.6
8  1963    1    0.0 < Same thing.
9  1963    2    0.0
10 1963    3    0.0
11 1963    4    0.0
12 1963    5    0.0

seq(tmp:12) + tmp - 1独自返回我想要的内容-

> tmp <- 8
> seq(tmp:12) + tmp - 1
[1]  8  9 10 11 12

但是当我在上面的代码中尝试时,它不起作用。我在做什么错了?

编辑

除了非标准的seq(x:y)版本,我还尝试了seq(x, y)的版本。这给了我与我上面提到的完全相同的结果。

我尝试了ind=seq(tmp, 12),它在单独执行时提供了我想要的东西,但是导致了输出中的NA错误,以及ind=seq(1, 12 - tmp + 1),它没有引起警告生成,但是导致了与ind=seq(tmp:12)的输出相同。

1 个答案:

答案 0 :(得分:1)

问题是堆栈函数将自变量转换为一个因数,因此当尝试将未知因素绑定到data.frame时,rbind函数失败。
在此解决方案中,我通过将s添加到data.frame函数中来确保stringsAsFactor= FALSE的所有列都不是因素。

prevdata<-read.table(header=TRUE, 
text="1     2     3     4     5     6     7
1963  74.1 155.2 226.4 186.7  37.2  23.6  23.6
1964 135.3 204.9 180.6 223.4 186.0 111.6 127.0
1965  69.3  24.2 151.9 321.3 121.7 147.8  44.1
1966  21.1 125.7  62.1 109.8 101.3  68.0 123.9
1967  12.4 118.0 245.4 269.6 139.1 117.1  63.1
1968  69.8  37.2 264.8 112.8 133.5  24.2  62.3")

names(prevdata)<-1:7
rnms <- rownames(prevdata)
z<-data.frame()  #initialize the dataframe prior to binding 
for (i in 1:nrow(prevdata)) {
  s <- stack(prevdata[i, ])

  #Need to convert factor column to numeric
  s$ind<-as.numeric(as.character(s$ind))
  #need to prevent the characters strings from being converted to factors
  z <- rbind(z, data.frame(year=rnms[i], month=s[2], values=s[1], stringsAsFactors = FALSE)) 

  # Get months remaining.
  tmp <- nrow(s)+1 
  # try to assign the data for missing months as zero. 
  z <- rbind(z, data.frame(year=rnms[i], ind=seq(tmp, 12), values=0)) 
}                            
colnames(z) <- c("YEAR", "MONTH", "values")

此解决方案有效,有更好的方法来解决此问题。例如,您可以将8到12列添加到原始数据帧框架上,然后通过重塑,熔化或tidyr:gather转换为长格式

编辑:

使用tidyr软件包:

prevdata[,8:12]<-0
names(prevdata)<-1:12
prevdata$year<-row.names(prevdata)
library(tidyr)
z<-gather(prevdata, month, values, -year)
z[order(z$YEAR, z$MONTH),]