Используя предоставленную вами ссылку на sharepoint, я сделал компактный mcve , который фиксирует большинство нарушений в полном наборе данных. Основной проблемой были пустые data.frames, и их было не сложно найти, хотя не все из них имели (no data)
в имени файла. Хотя достаточно просто отбросить пустые data.frames, я решил оставить их, заполнив одну строку NA
s. Если эти строки оказываются неприятными, их достаточно легко удалить позже.
Я пробовал это на полном наборе данных, и он отлично работает.
Пример данных
# set.seed(2)
# filenames <- list.files("Foobot", recursive=TRUE, full.names=TRUE)
# filenames[sample(length(filenames), 5)][c(1, 4, 5)]
# ldf <- lapply(filenames, read.csv, stringsAsFactors=FALSE)
# s <- sapply(ldf, nrow) != 0
# ldf[s] <- lapply(ldf[s], function(x) x[sample(nrow(x), sample(2:3)),])
# ldf <- lapply(ldf, "rownames<-", NULL)
filenames <- c(
"Foobot/House 04 foobot data/House 04 bedroom/House 04 bed Mar 2019.csv",
"Foobot/House 03 foobot data/House 03 Living room/House 03 Liv May 2019.csv",
"Foobot/House 18 foobot data/House 18 living room/House 18 liv Feb 2019.csv")
ldf <- list(structure(list(time..s.=logical(0), Device.Local.Time=logical(0),
pm..ugm3.=logical(0), tmp..C.=logical(0), hum..pc.=logical(0),
co2..ppm.=logical(0), voc..ppb.=logical(0), allpollu....=logical(0),
X=logical(0)), class="data.frame", row.names=integer(0)),
structure(list(time..s.=c(1557342000L, 1556863500L),
Device.Local.Time=c("08/05/2019 20:00", "03/05/2019 07:05"),
pm..ugm3.=c(18.660004, 43.5), tmp..C.=c(17.73, 17.5), hum..pc.=c(55.947,
50.739), co2..ppm.=c(1187, 1003), voc..ppb.=c(328, 277),
allpollu....=c(45.99334, 59.928574)), row.names=c(NA, -2L),
class="data.frame"), structure(list(time..s.=c(1549291500L, 1550995200L,
1550111100L), Device.Local.Time=c("04/02/2019 14:45", "24/02/2019 08:00",
"14/02/2019 02:25"), pm..ugm3.=c(13.76001, 8.4700165, 11), tmp..C.=c(21.407,
16.972, 20.918), hum..pc.=c(48.643997, 55.678, 52.008), co2..ppm.=c(643, 910,
738), voc..ppb.=c(178, 251.5, 204.5), allpollu....=c(21.331438, 26.541447,
22.357143), X=c(NA, NA, NA)), row.names=c(NA, -3L), class="data.frame"))
Обработка
# One of the data.frames have zero rows
sapply(ldf, dim)
# [,1] [,2] [,3]
# [1,] 0 2 3
# [2,] 9 8 9
# Forcing all the data.frames to have at least one row results in
# padding with NAs for those that have less
ldf <- lapply(ldf,
function(x) data.frame(
lapply(x, "length<-", max(c(1, nrow(x)))),
stringsAsFactors=FALSE))
# Extract metadata from the directory names
dn <- do.call(rbind, strsplit(dirname(filenames), "/"))
dn <- dn[,-(1:(ncol(dn)-2))]
dn[,1] <- sub("^(House [0-9]+) .*", "\\1", dn[,1])
dn[,2] <- tolower(sub("^House [0-9]+ ", "", dn[,2]))
# Extract metadata from the base names
bn <- strsplit(sub("\\.csv$", "", basename(filenames)), " ")
bn <- t(sapply(bn, tail, 2))
# Combine and create Date column
dtf <- data.frame(dn, bn, stringsAsFactors=FALSE)
colnames(dtf) <- c("House", "Room", "Month", "Year")
dtf$Date <- as.Date(paste(dtf$Month, dtf$Year, 1), "%b %Y %d")
# Multi-argument intersection function
intsect <- function(x) {
Reduce(function(x, y) unique(y[match(x, y, 0L)]), x)
}
# Create vectors of valid column names
ldf.cn <- intsect(lapply(ldf, colnames))
dtf.cn <- colnames(dtf)
# Bind metadata and sensor data
ldf.cbind <- mapply(function(dtf, ldf) {
d <- cbind(c(dtf), ldf, stringsAsFactors=FALSE)
d <- d[, c("House", "Room", "Date", ldf.cn)]
d
}, split(dtf, 1:nrow(dtf)), ldf, SIMPLIFY=FALSE)
# Bind list of data.frames to one tall data.frame
ldf.rbind <- do.call(rbind, ldf.cbind)
# Convert to date-time
ldf.rbind$Device.Local.Time <- as.POSIXct(
ldf.rbind$Device.Local.Time, format="%d/%m/%Y %H:%M")
# Control that all the column classes make sense
sapply(ldf.rbind[1,], function(x) class(x)[1])
# House Room Date time..s.
# "character" "character" "Date" "integer"
# Device.Local.Time pm..ugm3. tmp..C. hum..pc.
# "POSIXct" "numeric" "numeric" "numeric"
# co2..ppm. voc..ppb. allpollu....
# "numeric" "numeric" "numeric"
# Inspect subset of final data.frame
ldf.rbind[sample(nrow(ldf.rbind), 3),]
# House Room Date time..s. Device.Local.Time
# 1 House 04 bedroom 2019-03-01 NA <NA>
# 3.3 House 18 living room 2019-02-01 1550111100 2019-02-14 02:25:00
# 2.2 House 03 living room 2019-05-01 1556863500 2019-05-03 07:05:00
# pm..ugm3. tmp..C. hum..pc. co2..ppm. voc..ppb. allpollu....
# 1 NA NA NA NA NA NA
# 3.3 11.0 20.918 52.008 738 204.5 22.35714
# 2.2 43.5 17.500 50.739 1003 277.0 59.92857