我有几个从csv文件提取的文件(NetCDF格式)。它是我下载的在线数据(月降水量网格数据“单元”有145行和139列) 我需要对每年(超过60年)的每月.csv文件进行求和,而不是对60次求和进行平均。
[出发!我曾经回答过的问题(不是最聪明的回答,而是我与之合作过的回答) PS:您可以创建一个包含日期和汇总的数据框,以非常快速地运行(如果您有大量数据,则以某种方式!)
1-第一步,我通过使用“数据”字段为每年创建“曲目”来组织我的所有数据,这虽然很长,但是很有效! ,
2-然后,我为每个月创建一个数据框,这里是1940年第一个月
df1<-read.csv2(file= "./1940-01-01.csv", sep="," , dec="." )
df2<-read.csv2(file= "./1940-02-01.csv", sep="," , dec="." )
...
df12<- read.csv2(file= "./1940-12-01.csv", sep="," , dec="." )
3-我对所有数据帧(每个单元格)求和,结果得到一个具有145(ROWS)和(141 COLUMNS)[相同尺寸]的数据帧
df_1940_sum <-df1+df2+df3+df4+df5+df6+df7+df8+df9+df10+df11+df12
4-我在我的曲目中将结果作为输出(csv文件)
write.table(df_sum, file="df_1940.csv", sep= ",")
答案 0 :(得分:1)
三种可能的解决方案,取决于您的严格需求。
从您的df
开始,我们创建三个列表。既然有这么多列,我将只关注少数几个列,但是所有其他列的计算都已完成。
dflst <- list(df, df, df)
df[, c("X", "V1", "V20", "V21", "V34")]
# X V1 V20 V21 V34
# 1 1 NA 63.06 36.64 11.69
# 2 2 NA 38.49 31.73 NA
TL,DR::我认为“ 案例3 ”可能是给定一些假设中三个案例中最好的(最灵活,最可靠),在这种情况下,您可以跳过这种“列名条件”和情况1-2,然后直接跳到底部。
在某些情况下的一个假设是,所有框架的尺寸均相同,并且所有列的顺序相同。如果始终都是这样,那么您可以跳过此“调节”步骤。
但是,如果这不是一个安全的假设,则可以从某种意义上“调节”它们。我将用三个伪造的框架列表进行演示,所有伪造的框架都略有不同:
somelst <- list(data.frame(x=1,y=2), data.frame(y=3, x=4), data.frame(x=5, z=6))
some_names <- names(somelst[[1]])
somelst <- lapply(somelst, `[`, some_names)
# Error in `[.data.frame`(X[[i]], ...) : undefined columns selected
要解决此问题,我们只需要使用通用名称即可。请注意,如果发生这种情况,则下一步将 静默丢弃 非标准列。
somelst <- lapply(somelst, function(l) l[, intersect(some_names, names(l)), drop=FALSE])
somelst
# [[1]]
# x y
# 1 1 2
# [[2]]
# x y
# 1 4 3
# [[3]]
# x
# 1 5
列的顺序现在是标准的,但是(与下面的情况1-2有关),我们缺少列。修复:
somelst <- lapply(somelst, function(l) { l[, setdiff(some_names, names(l))] <- NA; l; })
somelst
# [[1]]
# x y
# 1 1 2
# [[2]]
# x y
# 1 4 3
# [[3]]
# x y
# 1 5 NA
(最后一步只是为缺少的列添加全{NA
值。)
因此,我将其应用于我们的数据(尽管我们知道这里没有操作,因为所有列表元素都是相同的框架):
df_names <- names(dflst[[1]])
dflst <- lapply(dflst, function(l) l[, intersect(df_names, names(l)), drop=FALSE])
dflst <- lapply(dflst, function(l) { l[, setdiff(df_names, names(l))] <- NA; l; })
X
是数据我认为这不太可能,但是为了完整起见,我将其包括在内,以防最简单的情况确实是预期的:
out <- Reduce(`+`, dflst)
out[, c("X", "V1", "V20", "V21", "V34")]
# X V1 V20 V21 V34
# 1 3 NA 189.18 109.92 35.07
# 2 6 NA 115.47 95.19 NA
X
是密钥在这种情况下,我们只是将所有内容加在一起,而没有更改X
id。
注意:这假定所有ID均以相同顺序出现在所有帧中。。
out <- df # really just need "X" and the right number of columns
# ... none of the other values are used
out[,-1] <- Reduce(`+`, lapply(dflst, `[`, -1))
out[, c("X", "V1", "V20", "V21", "V34")]
# X V1 V20 V21 V34
# 1 1 NA 189.18 109.92 35.07
# 2 2 NA 115.47 95.19 NA
一个人可以通过以下方式验证这一假设:
identical(df$X, Reduce(function(a, b) if (identical(a,b)) a else FALSE, lapply(dflst, `[[`, "X")))
# [1] TRUE
任何区别都将表明造成更多(不是那么简单)的调节或案例3 (这仍然是我的总体建议)的原因。
在这种情况下,我们不必像对列名和顺序进行规范化那样对数据进行预处理,因为它是自然而然的。它确实假设列名是重要且标准的,这意味着如果在一个框架中看到"V22"
,则意味着在所有框架中都显示"V22"
,并且其他与"V22"
相同。
但是,不是不会假设一帧中的所有名称都在另一帧中,因此可以轻松处理缺少列的情况。如果它们都以相同的顺序存在(就像人们从自动化数据集中所期望的那样),那么它也同样有效。
这可以在base-R和data.table
中完成,但是我发现dplyr
(和家庭)的识字形式最容易证明:
library(dplyr)
library(purrr)
library(tidyr)
out <- map(dflst, ~ gather(., k, v, -X)) %>%
bind_rows(.) %>%
group_by(X, k) %>%
summarize(v = if (all(is.na(v))) NA_real_ else sum(v, na.rm = TRUE)) %>%
spread(k, v)
out[, c("X", "V1", "V20", "V21", "V34")]
# # A tibble: 2 x 5
# # Groups: X [2]
# X V1 V20 V21 V34
# <int> <dbl> <dbl> <dbl> <dbl>
# 1 1 NA 189. 110. 35.1
# 2 2 NA 115. 95.2 NA
(这是一个tibble
,其在控制台上的表示与原始帧有一些显着差异。值得注意的是"V20"
的值看起来有所不同,尽管在这种情况下,这只是tibble
这是使事情保持“整洁”的有效数字的好方法。如果您改为as.data.frame(out[, c("X", "V1", "V20", "V21", "V34")])
,则会看到结果相同。)
说明:
map(dflst, ...)
对列表中的每个帧执行某事; gather(., k, v, -X)
正在从“宽”格式转换为“长”格式,在这种格式下,单帧会这样:
gather(df, k, v, -X) %>% head(.)
# X k v
# 1 1 V1 NA
# 2 2 V1 NA
# 3 1 V2 NA
# 4 2 V2 NA
# 5 1 V3 NA
# 6 2 V3 NA
bind_rows(.)
正在将一帧帧组合成一个行级联的帧
group_by(X, k) %>% summarize(...)
进行按ID和按(原始)列的聚合,因此将所有X==1
和k=="V1"
合并为一行,等等。if (all(is.na(v))) NA_real_ else sum(v, na.rm = TRUE)
有点骇人听闻;通常我会做 just sum(v, na.rm = TRUE)
(否if
),但是其他情况下,将全{NA
字段保留为NA
,其中{ {1}}将其转换为sum
。我认为保持“该字段从未有过数据”这一想法很重要,因此,如果全部为0
,则保留为NA
,否则给出所有非NA
的总和字段。NA
从“长”格式转换为“宽”格式。