通过聚合行中的列来重塑数据

时间:2016-11-02 12:43:26

标签: r reshape2

我正面临重塑数据的问题,但我不确定reshape2包是否是解决方案。我需要重塑的原始数据以一种特殊的方式存储。它们是csv文件中的每日温度数据,这就是文件头的样子:

ID,YEAR,MONTH,NAME,ALTITUDE,REGION,LON,LAT,DATUM,TMAX1,TMAX2,......,TMAX31,TMIN1,TMIN2,..........,TMIN31

其中TMAX1代表MONTH中第1天的最高温度。然后,以下值是所有月份的最高温度。 TMIN1列给出了第1天的最低温度,依此类推,直到最后一列,该月的最后一天温度最低。如果一个月的时间少于31天,则该字段为空。

可以在link

找到简短的示例数据文件

需要重新格式化才能将数据保存在两个只包含四列的新文件中IDDATETEMPVALIDTEMP TEMP为{{{ 1}}或TMAX)具有电台ID,日期,温度(TMINTMAX)值和验证标志,如图所示:

enter image description here

考虑我的问题我应该创建一个包含所有可能日期的向量(在原始数据中只显示年份和月份,日期来自数据列号/名称),然后进行某种转置以适应每天{ {1}} / TMIN数据及其在新数据框中的相应日期。不确定是否可以通过reshape2完成此操作。

我使用reshape2进行了简单的首次尝试,但这会将TMAXTMIN作为不同的变量,而它们都是温度数据。我希望在名为TMAX1 / TMAXn的单个变量中融合所有TMAXn / TMIN

我将继续尝试解决问题,但非常感谢任何帮助

输出20个第一行原始数据文件

TMAX

3 个答案:

答案 0 :(得分:2)

您可以这样使用melt功能:

library(reshape2)
data <- read.csv("data_temp_orig.csv", header = TRUE)
allnames <- names(data)
idnames <- allnames[1:9]
tempnames <- allnames[10:71]
data_melt <- melt(data, id.vars = idnames, measure.vars = tempnames)

head(data_melt)
     ID YEAR MONTH    NAME ALTITUDE   REGION   LON    LAT  DATUM variable value
1 8008A 1942    12 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX1   155
2 8008A 1943     1 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX1   150
3 8008A 1943     2 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX1   190
4 8008A 1943     3 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX1   147
5 8008A 1943     4 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX1   215
6 8008A 1943     5 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX1   170

tail(data_melt)
        ID YEAR MONTH    NAME ALTITUDE   REGION   LON    LAT  DATUM variable value
2289 8008A 1945     7 VILLENA      486 ALICANTE 51562 383437 ETRS89   TMIN31   154
2290 8008A 1945     8 VILLENA      486 ALICANTE 51562 383437 ETRS89   TMIN31    90
2291 8008A 1945     9 VILLENA      486 ALICANTE 51562 383437 ETRS89   TMIN31    NA
2292 8008A 1945    10 VILLENA      486 ALICANTE 51562 383437 ETRS89   TMIN31    75
2293 8008A 1945    11 VILLENA      486 ALICANTE 51562 383437 ETRS89   TMIN31    NA
2294 8008A 1945    12 VILLENA      486 ALICANTE 51562 383437 ETRS89   TMIN31   -20

因此所有温度都在value列之下。这是你想要的吗?然后,您可以对不同变量进行分解并进行计算,meansum等。

要添加,要为日期创建新矢量:

data_melt <- separate(data = data_melt, 
                         col = variable, 
                         into = c("max/min", "day"), 
                         sep = 4)
data_melt$date <- as.Date(paste0(data_melt$YEAR, "-", data_melt$MONTH, "-", data_melt$day))

head(data_melt)
     ID YEAR MONTH    NAME ALTITUDE   REGION   LON    LAT  DATUM max/min day value       date
1 8008A 1942    12 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX   1   155 1942-12-01
2 8008A 1943     1 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX   1   150 1943-01-01
3 8008A 1943     2 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX   1   190 1943-02-01
4 8008A 1943     3 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX   1   147 1943-03-01
5 8008A 1943     4 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX   1   215 1943-04-01
6 8008A 1943     5 VILLENA      486 ALICANTE 51562 383437 ETRS89    TMAX   1   170 1943-05-01

class(data_melt$date)
[1] "Date"

答案 1 :(得分:1)

我希望这或多或少是你想要的:

library(data.table)
library(lubridate)

x = fread("/your/directory/data_temp_orig.csv")

m = melt(x, 
         id.vars = c("ID", "YEAR", "MONTH"),
         measure.vars = patterns("^TM"))

m[, fecha := ymd(paste(YEAR, MONTH, "01", sep = "-"))]
m[, c("YEAR", "MONTH") := NULL]

答案 2 :(得分:1)

此答案使用tidyrdplyr个包。

library(tidyr)
library(dplyr)
library(lubridate)
temp_orig <- read.csv("data-raw/data_temp_orig.csv", 
                     stringsAsFactors = FALSE) 
# I prefer lowercase column names
names(temp_orig) <- tolower(names(temp_orig))

temp2 <- temp_orig %>% 
    # select only interesting columns
    select(id, year, month, tmax1:tmin31) %>% 
    # reshape in long format
    gather(key, temp, -id, -year, -month) %>% 
    # separate at the fourth character
    separate(key, c("key", "day"), sep = 4) %>%  
    # Combine year, month, day in a single date
    mutate(date = ymd(paste(year,month,day))) 

过滤最低温度

tmindata <- temp2 %>%         
    # filter for existing dates
    filter(key == "tmin" & !is.na(date)) %>% 
    # Remove year month day
    select(-year, -month, -day) 

head(tmindata)
#      id  key temp       date
# 1 8008A tmin   20 1942-12-01
# 2 8008A tmin    5 1943-01-01
# 3 8008A tmin   55 1943-02-01
# 4 8008A tmin   20 1943-03-01
# 5 8008A tmin   40 1943-04-01
# 6 8008A tmin  109 1943-05-01

您也可以这样做来过滤tmax数据

你可能已经注意到来自Warning message: 40 failed to parse.上方的一个警告,因为某些日期(例如2月30日)不存在且没有数据:

tmissingdate <- temp2 %>% 
    filter(is.na(date))
head(tmissingdate)
#      id year month  key day temp date
# 1 8008A 1943     2 tmax  29   NA <NA>
# 2 8008A 1945     2 tmax  29   NA <NA>
# 3 8008A 1943     2 tmax  30   NA <NA>
# 4 8008A 1944     2 tmax  30   NA <NA>
# 5 8008A 1945     2 tmax  30   NA <NA>
# 6 8008A 1943     2 tmax  31   NA <NA>

数据图

library(ggplot2)
ggplot(temp2, aes(x =  date, y = temp, color = key)) +
    geom_line()

enter image description here