A pipeline for evaluating the PS2 data from Sarah Kezar’s experiment This is a part of a series of experiments on Parthenium sp. from various locations.

PS2 data loading

OK - now let’s explore whats happening in the PS2 data!

Because the original output file is having some nonsense lines as we export it from the PS2 analyzer - we need to remove them:

PS2 <- read.csv("Exp_10190_Data_Analysis_MMJ.csv")
PS2

For this specific experiment - in order to analyze the results per OVERALL canopy - let’s keep ONLY “all”

PS3 <- subset(PS2, PS2$Obj.No == "All")
PS3

get only the columns that are informative biologically (for now):

colnames(PS3)
##  [1] "File"           "Date"           "Time"           "Obj.No"        
##  [5] "nTmPam"         "Obj.Size"       "Obj.Xc"         "Obj.Yc"        
##  [9] "Fv.Fm"          "s.d."           "Fq..Fm."        "s.d..1"        
## [13] "NPQ"            "s.d..2"         "F0."            "s.d..3"        
## [17] "qP"             "s.d..4"         "qN"             "s.d..5"        
## [21] "qL"             "s.d..6"         "qE"             "s.d..7"        
## [25] "qI"             "s.d..8"         "D.no"           "s.d..9"        
## [29] "D.npq"          "s.d..10"        "npq.t."         "s.d..11"       
## [33] "Red"            "s.d..12"        "Green"          "s.d..13"       
## [37] "Blue"           "s.d..14"        "Hue"            "s.d..15"       
## [41] "Saturation"     "s.d..16"        "Value"          "s.d..17"       
## [45] "SpcGrn"         "s.d..18"        "FarRed"         "s.d..19"       
## [49] "Nir"            "s.d..20"        "ChlIdx"         "s.d..21"       
## [53] "AriIdx"         "s.d..22"        "NDVI"           "s.d..23"       
## [57] "Border"         "Mask.Border"    "Points"         "Area..CH."     
## [61] "Mask.Area..CH." "X.Centre"       "Y.Centre"       "Radius"        
## [65] "Area..MC."      "Mask.Area..MC." "Width"          "Height"        
## [69] "Area..MR."      "Mask.Area..MR." "Alpha"          "Size..SK."     
## [73] "Junction..SK."  "Endpoint..SK."  "Path..SK."
PS4 <- PS3[,c(1:3, 6, 9, 11, 13, 17, 19, 21, 23, 25, 27, 29, 31, 51, 53, 55)]
PS4
library(ggplot2)
library(ggpubr)
PS4$Date <- as.factor(PS4$Date)
lgraph <- ggplot(data=PS4, aes(x= Date, y=ChlIdx)) 
lgraph <- lgraph + geom_point(alpha = 0.7) + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
lgraph <- lgraph + ylab("Chlorophylll Index") + xlab("days after stress")
lgraph

OK - so this dataset contains actually three experiments - batch 01 from Sarah’s experiment from Dec. 2 to Dec. 16 - then Akhilesh’s dataset from Dec. 18 to Jan. 02 - then batch 02 from Sarah’s experiment from Jan. 03 to Jan. 17th

We also have four trays that were used as “test” - let’s remove them too

Let’s isolate only the measurement from batch 01:

want <- c("20241218", "20241219", "20241220", "20241221", "20241222", "20241223", "20241224", "20241225", "20241226", "20241227", "20241228", "20241229", "20241230", "20241230", "20241231", "20250101")


PS4 <- subset(PS4, PS4$Date %in% want)
PS4$Date <- sub("20250101", "20241232", PS4$Date)

lgraph <- ggplot(data=PS4, aes(x= Date, y=ChlIdx)) 
lgraph <- lgraph + geom_point(alpha = 0.7) + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
lgraph <- lgraph + ylab("Chlorophylll Index") + xlab("days after stress")
lgraph

There are still some odd measurements - but that’s probably because we are including the “test” trays in there - which we can remove later.

This is great start, but lets isolate the measurement per tray ID - which is the third item in the File name (HDR_ExpID_TrayID_roundID.INF)

How do we get there?

strsplit(PS4$File[1], "_")[[1]][3]
## [1] "39933"

Now - lets isolate it for the entire data sheet:

for(i in 1:nrow(PS4)){
  PS4$tray.ID[i] <- strsplit(PS4$File[i], "_")[[1]][3]
}
length(unique(PS4$tray.ID))
## [1] 64
unique(PS4$Date)
##  [1] "20241218" "20241219" "20241220" "20241221" "20241222" "20241223"
##  [7] "20241224" "20241225" "20241226" "20241227" "20241228" "20241229"
## [13] "20241230" "20241231" "20241232"

Let’s transfer date and time into TOE.

for(i in 1:nrow(PS4)){
  PS4$month <- substr(PS4$Date, 5, 6)
  PS4$day <- substr(PS4$Date, 7, 8)
  PS4$hour <- substr(PS4$Time, 1, 2)
}
PS4

Trays were loaded on Dec 18th at around 13:00

PS4$TOE <- (as.numeric(as.character(PS4$day)) - 18)*24 + (as.numeric(as.character(PS4$hour)) - 13)
unique(PS4$TOE)
##   [1]  -6   7  18  31  45  55  68  79  90 103 114 127 138 151 162 175 186 199
##  [19] 210 223 234 247 258 271 282 295 306 310 319 330 334  46  69  -5   8  19
##  [37]  56 248 259 272 283 296 307 320 331  32  80 115 128 139 152 163 176 187
##  [55] 211 224 235  91 104 200 311 335  43  66  44  47  67  70  -4   9 321 249
##  [73] 273 284 308 332  20 260 297 116 140 153 164 188 212 225  81  92 105 129
##  [91] 177 236 312 336 201  48  10  71 322 250 274 285 333
PS4

OK - then we have an issue with the FvFm being correct for one set of the data - and the other traits (FqFm and such) for other row. We need to correct it first:

# Get data containing right measurements into two separate datasets:
FvFm_data <- subset(PS4, PS4$Fv.Fm > 0)
notFvFm_data <- subset(PS4, PS4$Fv.Fm < 0)
# Get rid of collumns containing nonsense
FvFm_data <- FvFm_data[,c(1:5)]
notFvFm_data <- notFvFm_data[,c(1:4,6:23)]
FvFm_data
notFvFm_data

Now - let’s merge them together:

PS5 <- merge(FvFm_data, notFvFm_data, by =c("File", "Date", "Time", "Obj.Size"))
PS5

Lets have a look at how the data looks like now:

lgraph <- ggplot(data=PS5, aes(x= TOE, y=Fv.Fm, group = tray.ID)) 
lgraph <- lgraph + geom_line(alpha = 0.7) 
lgraph <- lgraph + ylab("Maximum Quantum Yield (Fv/Fm)") + xlab("Hours of Imaging")
lgraph

As you can see - there are some lines that are not exactly the same timepoints - so we will get in trouble when calculating averages. Therefore - we need to do splines!

Splines for ALL PS2 traits

So - let’s first isolate one plant to establish our spline calculations

PS6 <- PS5
max(PS6$TOE)
## [1] 336
hours <- seq(0, 336, by = 12)
hours
##  [1]   0  12  24  36  48  60  72  84  96 108 120 132 144 156 168 180 192 204 216
## [20] 228 240 252 264 276 288 300 312 324 336
length(hours)
## [1] 29
temp <- subset(PS6, PS6$tray.ID == unique(PS6$tray.ID)[1])
temp$TOE <- as.numeric(as.character(temp$TOE))
temp <- temp[order(temp$TOE, decreasing = F),]
temp$TOE
##  [1]   7  18  31  45  55  68  79  90 103 114 127 138 151 162 175 186 199 210 223
## [20] 234 247 258 271 282 295 306 310 319 330 334

Fv/Fm

plot.spl <- with(temp, smooth.spline(TOE, Fv.Fm, df = 29))
plot(Fv.Fm ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

Fq/Fm

plot.spl <- with(temp, smooth.spline(TOE, Fq..Fm., df = 29))
plot(Fq..Fm. ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

NPQ

plot.spl <- with(temp, smooth.spline(TOE, NPQ, df = 29))
plot(NPQ ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

qP

plot.spl <- with(temp, smooth.spline(TOE, qP, df = 29))
plot(qP ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

qN

plot.spl <- with(temp, smooth.spline(TOE, qN, df = 29))
plot(qN ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

qL

plot.spl <- with(temp, smooth.spline(TOE, qL, df = 29))
plot(qL ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

qE

plot.spl <- with(temp, smooth.spline(TOE, qE, df = 29))
plot(qE ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

qI

plot.spl <- with(temp, smooth.spline(TOE, qI, df = 29))
plot(qI ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

фno

plot.spl <- with(temp, smooth.spline(TOE, D.no, df = 29))
plot(D.no ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

фnpq

plot.spl <- with(temp, smooth.spline(TOE, D.npq, df = 29))
plot(D.npq ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

npq(t)

plot.spl <- with(temp, smooth.spline(TOE, npq.t., df = 29))
plot(npq.t. ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

ChlIdx

plot.spl <- with(temp, smooth.spline(TOE, ChlIdx, df = 29))
plot(ChlIdx ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

AriIdx

plot.spl <- with(temp, smooth.spline(TOE, AriIdx, df = 29))
plot(AriIdx ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

NDVI

plot.spl <- with(temp, smooth.spline(TOE, NDVI, df = 29))
plot(NDVI ~ TOE, data = temp)
lines(plot.spl, col = "blue")
lines(predict(plot.spl, hours), col = "red")

Then - let’s save all of the information into one file

PS6
# CHANGE last thing into trait name
names <- c(text = "tray.ID", "TOE", "Fv.Fm", "Fq.Fm", "NPQ", "qP", "qN", "qL", "qE", "qI", "phiNO", "phiNPQ", "npq.t", "ChlIdx", "AriIdx", "NDVI")
spline_data <- data.frame()
for (k in names) {
  spline_data[[k]] <- as.character()}
pred_temp <- predict(plot.spl, hours)
length(pred_temp$x)
## [1] 29
spline_data[1:29,1] <- temp$tray.ID[1]
spline_data[1:29,2] <- pred_temp$x
plot.spl <- with(temp, smooth.spline(TOE, Fv.Fm, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,3] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, Fq..Fm., df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,4] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, NPQ, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,5] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, qP, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,6] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, qN, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,7] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, qL, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,8] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, qE, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,9] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, qI, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,10] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, D.no, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,11] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, D.npq, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,12] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, npq.t., df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,13] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, ChlIdx, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,14] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, AriIdx, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,15] <- pred_temp$y
plot.spl <- with(temp, smooth.spline(TOE, NDVI, df = 29))
pred_temp <- predict(plot.spl, hours)
spline_data[1:29,16] <- pred_temp$y

final_spline <- spline_data
final_spline
all_plants <- unique(PS5$tray.ID)
all_plants
##  [1] "39933" "39934" "39935" "39936" "39937" "39938" "39939" "39940" "39941"
## [10] "39942" "39943" "39944" "39945" "39946" "39947" "39948" "39949" "39950"
## [19] "39951" "39952" "39953" "39954" "39955" "39956" "39957" "39958" "39959"
## [28] "39960" "39961" "39962" "39963" "39964" "39965" "39966" "39967" "39968"
## [37] "39969" "39970" "39971" "39972" "39973" "39974" "39975" "39976" "39977"
## [46] "39978" "39979" "39980" "39981" "39982" "39983" "39984" "39985" "39986"
## [55] "39987" "39988" "39989" "39990" "39991" "39992" "39993" "39994" "39995"
for(i in 2:60){
    temp <- subset(PS6, PS6$tray.ID == unique(PS6$tray.ID)[i])

   if (dim(temp)[1] > 3) {
        temp$TOE <- as.numeric(as.character(temp$TOE))
        temp <- temp[order(temp$TOE, decreasing = F),]
        spline_data[1:29,1] <- temp$tray.ID[1]
        spline_data[1:29,2] <- hours
        plot.spl <- with(temp, smooth.spline(TOE, Fv.Fm, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,3] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, Fq..Fm., df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,4] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, NPQ, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,5] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, qP, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,6] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, qN, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,7] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, qL, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,8] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, qE, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,9] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, qI, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,10] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, D.no, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,11] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, D.npq, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,12] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, npq.t., df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,13] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, ChlIdx, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,14] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, AriIdx, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,15] <- pred_temp$y
        plot.spl <- with(temp, smooth.spline(TOE, NDVI, df = 29))
        pred_temp <- predict(plot.spl, hours)
        spline_data[1:29,16] <- pred_temp$y
        final_spline <- rbind(final_spline, spline_data)
  } else {
        spline_data[1:29,1] <- temp$tray.ID[1]
        spline_data[1:29,2] <- hours
        spline_data[1:29,3] <- 0
        spline_data[1:29,4] <- 0
        spline_data[1:29,5] <- 0
        spline_data[1:29,6] <- 0
        spline_data[1:29,7] <- 0
        spline_data[1:29,8] <- 0
        spline_data[1:29,9] <- 0
        spline_data[1:29,10] <- 0
        spline_data[1:29,11] <- 0
        spline_data[1:29,12] <- 0
        spline_data[1:29,13] <- 0
        spline_data[1:29,14] <- 0
        spline_data[1:29,15] <- 0
        spline_data[1:29,16] <- 0
        final_spline <- rbind(final_spline, spline_data)
  }}
## Warning in smooth.spline(TOE, Fv.Fm, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, Fq..Fm., df = 29): not using invalid df; must
## have 1 < df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, NPQ, df = 29): not using invalid df; must have 1
## < df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, qP, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, qN, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, qL, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, qE, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, qI, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, D.no, df = 29): not using invalid df; must have 1
## < df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, D.npq, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, npq.t., df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, ChlIdx, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, AriIdx, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, NDVI, df = 29): not using invalid df; must have 1
## < df <= n := #{unique x} = 24
## Warning in smooth.spline(TOE, Fv.Fm, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, Fq..Fm., df = 29): not using invalid df; must
## have 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, NPQ, df = 29): not using invalid df; must have 1
## < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qP, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qN, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qL, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qE, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qI, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, D.no, df = 29): not using invalid df; must have 1
## < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, D.npq, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, npq.t., df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, ChlIdx, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, AriIdx, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, NDVI, df = 29): not using invalid df; must have 1
## < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, Fv.Fm, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, Fq..Fm., df = 29): not using invalid df; must
## have 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, NPQ, df = 29): not using invalid df; must have 1
## < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qP, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qN, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qL, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qE, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, qI, df = 29): not using invalid df; must have 1 <
## df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, D.no, df = 29): not using invalid df; must have 1
## < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, D.npq, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, npq.t., df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, ChlIdx, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, AriIdx, df = 29): not using invalid df; must have
## 1 < df <= n := #{unique x} = 28
## Warning in smooth.spline(TOE, NDVI, df = 29): not using invalid df; must have 1
## < df <= n := #{unique x} = 28
final_spline

Let’s change the collumns also to numeric - otherwise it will be tought to plot this:

final_spline2 <- final_spline
final_spline2[2:16] <- sapply(final_spline2[2:16],as.numeric)
final_spline2

OK - that’s all - but just before we finish this - let’s save all of the data:

write.csv(final_spline2, "Akhilesh_2024Dec.PS2.csv", row.names = F)