Read in Data

data=read.csv("CombinedData.csv")

Chat GPT Input: I need to go from wide to long format in R. Columns are samples (A, B,C) and dose (0,5,10,25). It appended a number for replications (A.10.1, A.10.2) So this would be Sample A, dose of 10, replicates 1 and 2. Please provide code to go to long format. Include a screenshot of the data.

Change Data to Long Format

We converted the dataset from a wide format to a long format to make it easier to analyze and visualize in R using tidyverse tools. Originally, each column represented a unique experimental condition, where the column names encoded the sample identity (e.g., A or B), dosage level (0, 5, 10, or 25), and replicate number (e.g., .1 or .2). Using pivot_longer(), we combined all measurement columns into a single response column (OD) while preserving the time variable. We then used separate() to split the original column names into three new variables: Sample, Dose, and Replicate. Missing replicate identifiers were assigned a value of 0, allowing columns such as A.10, A.10.1, and A.10.2 to be interpreted consistently as replicate 0, 1, and 2 of Sample A at dose 10. This restructuring produces a tidy dataset in which each row represents a single observation at one time point, making downstream statistical analysis and ggplot visualization much more straightforward.

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.0     ✔ readr     2.2.0
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.2     ✔ tibble    3.3.1
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ purrr     1.2.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(tidyverse)  # Loads the tidyverse collection of data wrangling packages

dat_long <- data %>%
  pivot_longer(
    cols = -Time,
    names_to = "well_name",
    values_to = "OD"
  ) %>%
  mutate(
    is_blank = str_detect(well_name, "^Blank")
  ) %>%
  mutate(
    Sample = if_else(is_blank, "Blank", str_extract(well_name, "^[ABC]")),
    Glucose = if_else(is_blank, "4YPD", str_extract(well_name, "(?<=_)[0-9.]+(?=_)")),
    Replicate = if_else(is_blank, str_extract(well_name, "[A-H][0-9]+$"),
                        str_extract(well_name, "(?<=_[0-9.]_)[0-9]+|(?<=_[0-9][.]?[0-9]?_)[0-9]+")),
    Treatment = case_when(
      str_detect(well_name, "_Met") ~ "Met",
      str_detect(well_name, "_Control") ~ "Control",
      str_detect(well_name, "_NoMet") ~ "Control",
      TRUE ~ "Control"
    )
  )


dat_long <- dat_long %>%
  filter(Sample != "Blank")


# data_long <- data %>%  # Start with the original dataset called "data"
#   pivot_longer(  # Convert data from wide format to long format
#     cols = -Time,  # Use all columns except the Time column
#     names_to = "well_name",  # Store original column names in a new column called well_name
#     values_to = "OD"  # Store OD600 values in a new column called OD
#   ) %>%  
#   separate(  # Split the well_name column into multiple columns
#     well_name,  # Column being split
#     into = c("Sample", "Dose", "Replicate"),  # Names of new columns created
#     sep = "\\.",  # Split wherever there is a period "."
#     fill = "right"  # If replicate is missing, leave it blank instead of erroring
#   ) %>%
#   mutate(  # Modify and clean columns
#     Dose = as.numeric(Dose),  # Convert Dose from text to numeric
#     Replicate = replace_na(Replicate, "0"),  # Replace missing replicate values with 0
#     Replicate = as.numeric(Replicate)  # Convert Replicate from text to numeric
#   )

dat_long=subset(dat_long, Glucose != "4")

#Statistical Comparison

growth_dat <- dat_long %>%
  group_by(Time, Glucose, Replicate, Treatment) %>%
  dplyr::summarize(
    OD = mean(OD, na.rm = TRUE),
    .groups = "drop"
  )

growth_summary <- growth_dat %>%
  group_by(Time, Glucose, Treatment) %>%
  dplyr::summarize(
    Mean_OD = mean(OD, na.rm = TRUE),
    SE = sd(OD, na.rm = TRUE) / sqrt(n()),
    .groups = "drop"
  )


head(growth_dat)
## # A tibble: 6 × 5
##   Time    Glucose Replicate Treatment    OD
##   <chr>   <chr>   <chr>     <chr>     <dbl>
## 1 0:00:00 0.5     1         Control   0.223
## 2 0:00:00 0.5     1         Met       0.214
## 3 0:00:00 0.5     2         Control   0.226
## 4 0:00:00 0.5     2         Met       0.214
## 5 0:00:00 0.5     3         Control   0.235
## 6 0:00:00 0.5     3         Met       0.217
nrow(growth_dat)
## [1] 1128
library(lubridate)

library(tidyverse)

growth_summary <- growth_summary %>%
  mutate(
    Time_chr = as.character(Time),

    # Split off day if SoftMax uses format like 1.00:30:00
    Day = ifelse(str_detect(Time_chr, "\\."),
                 as.numeric(str_extract(Time_chr, "^[0-9]+")),
                 0),

    Time_no_day = ifelse(str_detect(Time_chr, "\\."),
                         str_replace(Time_chr, "^[0-9]+\\.", ""),
                         Time_chr),

    Hours = as.numeric(str_extract(Time_no_day, "^[0-9]+")),
    Minutes = as.numeric(str_extract(Time_no_day, "(?<=:)[0-9]+")),
    
    Time_hr = Day * 24 + Hours + Minutes / 60
  )

growth_summary %>%
  select(Time, Time_hr) %>%
  distinct() %>%
  tail(20)
## # A tibble: 20 × 2
##    Time     Time_hr
##    <chr>      <dbl>
##  1 22:00:00    22  
##  2 22:30:00    22.5
##  3 23:00:00    23  
##  4 23:30:00    23.5
##  5 2:00:00      2  
##  6 2:30:00      2.5
##  7 3:00:00      3  
##  8 3:30:00      3.5
##  9 4:00:00      4  
## 10 4:30:00      4.5
## 11 5:00:00      5  
## 12 5:30:00      5.5
## 13 6:00:00      6  
## 14 6:30:00      6.5
## 15 7:00:00      7  
## 16 7:30:00      7.5
## 17 8:00:00      8  
## 18 8:30:00      8.5
## 19 9:00:00      9  
## 20 9:30:00      9.5
ggplot(
  growth_summary,
  aes(
    x = Time_hr,
    y = Mean_OD,
    color = Treatment,
    fill = Treatment
  )
) +
  geom_ribbon(
    aes(
      ymin = Mean_OD - SE,
      ymax = Mean_OD + SE
    ),
    alpha = 0.2,
    color = NA
  ) +
  geom_line(linewidth = 1.2) +
  facet_wrap(~ Glucose, nrow = 1) +
  labs(
    x = "Time (hours)",
    y = "Mean OD600 ± SE",
    color = "Treatment",
    fill = "Treatment"
  ) +
  theme_classic(base_size = 14)

ggplot(
  growth_summary,
  aes(
    x = Time_hr,
    y = Mean_OD,
    color = Treatment,
    fill = Treatment
  )
) +
  geom_ribbon(
    aes(
      ymin = Mean_OD - SE,
      ymax = Mean_OD + SE
    ),
    alpha = 0.2,
    color = NA
  ) +
  geom_line(linewidth = 1.2) +
  facet_wrap(~ Glucose, nrow = 1) +
  labs(
    x = "Time (hours)",
    y = "Mean OD600 ± SE",
    color = "Treatment",
    fill = "Treatment"
  ) +
  theme_classic(base_size = 14) +
coord_cartesian(
  ylim = c(0.9, 1.5)
)

Growth curves were generated to examine the effects of prior glucose history and metformin treatment on yeast proliferation during 48 hours of refeeding. Cultures conditioned in either 0.5% or 2% glucose exhibited similar growth dynamics, with all groups rapidly entering exponential growth and reaching comparable stationary-phase optical densities. Metformin treatment (10 mM) produced only subtle differences in growth, including a slightly shorter lag phase and marginally higher final optical density, but no large inhibitory or stimulatory effects were observed. Overall, these data suggest that metformin at the selected concentration has minimal influence on overall cell proliferation during refeeding.

AUC

library(MESS)

growth_dat <- growth_dat %>%
  mutate(Time = as.character(Time))

# Check if days are present
growth_dat %>%
  filter(grepl("\\.", Time)) %>%
  select(Time) %>%
  distinct()
## # A tibble: 46 × 1
##    Time      
##    <chr>     
##  1 1.00:00:00
##  2 1.00:30:00
##  3 1.01:00:00
##  4 1.01:30:00
##  5 1.02:00:00
##  6 1.02:30:00
##  7 1.03:00:00
##  8 1.03:30:00
##  9 1.04:00:00
## 10 1.04:30:00
## # ℹ 36 more rows
growth_dat <- growth_dat %>%
  mutate(
    Day = ifelse(
      grepl("\\.", Time),
      as.numeric(sub("\\..*", "", Time)),
      0
    ),

    Time_no_day = ifelse(
      grepl("\\.", Time),
      sub("^[0-9]+\\.", "", Time),
      Time
    )
  ) %>%
  separate(
    Time_no_day,
    into = c("Hour","Minute","Second"),
    sep = ":",
    convert = TRUE
  ) %>%
  mutate(
    Time_hr = Day*24 + Hour + Minute/60
  )
## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `Day = ifelse(...)`.
## Caused by warning in `ifelse()`:
## ! NAs introduced by coercion
library(MESS)
library(dplyr)

library(dplyr)
library(MESS)

auc_dat <- growth_dat %>%
  ungroup() %>%
  group_by(
    .data$Glucose,
    .data$Replicate,
    .data$Treatment,
    .data$Time_hr
  ) %>%
  dplyr::summarize(
    OD_mean = mean(.data$OD, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  dplyr::arrange(
    .data$Glucose,
    .data$Replicate,
    .data$Treatment,
    .data$Time_hr
  ) %>%
  group_by(
    .data$Glucose,
    .data$Replicate,
    .data$Treatment
  ) %>%
  dplyr::summarize(
    AUC = MESS::auc(.data$Time_hr, .data$OD_mean),
    .groups = "drop"
  )

ggplot(
  auc_dat,
  aes(x = Treatment, y = AUC, fill = Treatment)
) +
  geom_boxplot(alpha = 0.7, outlier.shape = NA) +
  geom_jitter(width = 0.1, size = 3) +
  facet_wrap(~ Glucose) +
  theme_classic(base_size = 14) +
  labs(
    x = "Treatment",
    y = "Area under the growth curve",
    fill = "Treatment"
  )

model_auc <- lm(AUC ~ Glucose * Treatment, data = auc_dat)

anova(model_auc)
## Analysis of Variance Table
## 
## Response: AUC
##                   Df Sum Sq Mean Sq F value Pr(>F)
## Glucose            1  1.449  1.4493  0.2526 0.6288
## Treatment          1  6.754  6.7543  1.1772 0.3095
## Glucose:Treatment  1  1.764  1.7637  0.3074 0.5944
## Residuals          8 45.899  5.7373
summary(model_auc)
## 
## Call:
## lm(formula = AUC ~ Glucose * Treatment, data = auc_dat)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.0747 -1.2084 -0.6386  1.6527  3.4210 
## 
## Coefficients:
##                       Estimate Std. Error t value Pr(>|t|)    
## (Intercept)           60.80081    1.38291  43.966  7.9e-11 ***
## Glucose2              -0.07169    1.95573  -0.037    0.972    
## TreatmentMet           0.73372    1.95573   0.375    0.717    
## Glucose2:TreatmentMet  1.53350    2.76582   0.554    0.594    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.395 on 8 degrees of freedom
## Multiple R-squared:  0.1784, Adjusted R-squared:  -0.1297 
## F-statistic: 0.5791 on 3 and 8 DF,  p-value: 0.645
aucdat2=subset(auc_dat, Glucose != 4)
model_auc2 <- lm(AUC ~ Glucose * Treatment, data = aucdat2)
anova(model_auc2)
## Analysis of Variance Table
## 
## Response: AUC
##                   Df Sum Sq Mean Sq F value Pr(>F)
## Glucose            1  1.449  1.4493  0.2526 0.6288
## Treatment          1  6.754  6.7543  1.1772 0.3095
## Glucose:Treatment  1  1.764  1.7637  0.3074 0.5944
## Residuals          8 45.899  5.7373

To quantify cumulative growth over the 48-hour experiment, the area under each growth curve (AUC) was calculated for each biological replicate. Although metformin-treated cultures exhibited slightly higher AUC values than untreated controls in both glucose histories, linear modeling detected no significant effects of glucose history, metformin treatment, or their interaction (all P > 0.30). These findings indicate that neither prior nutritional history nor metformin substantially altered total biomass accumulation over the duration of the experiment, supporting the conclusion that 10 mM metformin has relatively modest effects on overall growth.

Nile Red

nile_raw=read.csv("Sonja_NR_complete.csv")

library(tidyverse)

nile_summary <- nile_raw %>%
  group_by(History, Replicate, Treatment) %>%
  summarize(
    Mean_Fluorescence = mean(Reading, na.rm = TRUE),
    .groups = "drop"
  )

nile_summary
## # A tibble: 36 × 4
##    History Replicate Treatment Mean_Fluorescence
##      <dbl> <chr>     <chr>                 <dbl>
##  1     0.5 A         Control                285.
##  2     0.5 A         Metformin              466.
##  3     0.5 B         Control                348.
##  4     0.5 B         Metformin              468.
##  5     0.5 C         Control                223.
##  6     0.5 C         Metformin              541.
##  7     0.5 D         Control                161.
##  8     0.5 D         Metformin              275.
##  9     0.5 E         Control                290.
## 10     0.5 E         Metformin              131.
## # ℹ 26 more rows
ggplot(
  nile_summary,
  aes(x = Treatment, y = Mean_Fluorescence, fill = Treatment)
) +
  geom_boxplot(alpha = 0.7, outlier.shape = NA) +
  geom_jitter(width = 0.1, size = 3) +
  facet_wrap(~ History) +
  theme_classic(base_size = 14) +
  labs(
    x = "Treatment",
    y = "Nile Red fluorescence",
    fill = "Treatment"
  )

model_nile <- lm(
  Mean_Fluorescence ~ as.factor(History) * Treatment,
  data = nile_summary
)

anova(model_nile)
## Analysis of Variance Table
## 
## Response: Mean_Fluorescence
##                              Df Sum Sq Mean Sq F value  Pr(>F)  
## as.factor(History)            1  52331   52331  6.8609 0.01336 *
## Treatment                     1  20778   20778  2.7240 0.10863  
## as.factor(History):Treatment  1  11691   11691  1.5328 0.22471  
## Residuals                    32 244080    7628                  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
summary(model_nile)
## 
## Call:
## lm(formula = Mean_Fluorescence ~ as.factor(History) * Treatment, 
##     data = nile_summary)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -192.051  -51.621    2.779   52.067  218.444 
## 
## Coefficients:
##                                        Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                              238.94      29.11   8.208 2.24e-09 ***
## as.factor(History)2                      -40.21      41.17  -0.977   0.3360    
## TreatmentMetformin                        84.09      41.17   2.042   0.0494 *  
## as.factor(History)2:TreatmentMetformin   -72.08      58.22  -1.238   0.2247    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 87.34 on 32 degrees of freedom
## Multiple R-squared:  0.2578, Adjusted R-squared:  0.1883 
## F-statistic: 3.706 on 3 and 32 DF,  p-value: 0.02143
library(emmeans)
## Welcome to emmeans.
## Caution: You lose important information if you filter this package's results.
## See '? untidy'
emm_nile <- emmeans(
  model_nile,
  ~ Treatment | History
)

pairs(emm_nile)
## History = 0.5:
##  contrast            estimate   SE df t.ratio p.value
##  Control - Metformin    -84.1 41.2 32  -2.042  0.0494
## 
## History = 2.0:
##  contrast            estimate   SE df t.ratio p.value
##  Control - Metformin    -12.0 41.2 32  -0.292  0.7725

Neutral lipid accumulation was assessed using Nile Red fluorescence following 48 hours of refeeding. In contrast to the growth analyses, glucose history significantly influenced lipid accumulation (P = 0.013), whereas the overall effect of metformin was not significant (P = 0.109). However, post hoc comparisons revealed that metformin significantly increased Nile Red fluorescence in cells previously conditioned under nutrient restriction (0.5% glucose; P = 0.049), while no significant effect of metformin was observed in cells conditioned in 2% glucose. These findings suggest that prior nutritional history alters the metabolic response to metformin despite having relatively little effect on overall cell growth, supporting the hypothesis that nutrient restriction induces persistent metabolic changes that influence subsequent responses during refeeding.

What this might mean:

The common teaching is that metformin “reduces lipid accumulation.” That’s an oversimplification. Metformin’s primary action is not to directly inhibit lipid synthesis. Instead, it alters cellular energy sensing by inhibiting mitochondrial respiration (Complex I in mammalian cells) and activating energy-stress pathways such as AMPK (or the analogous SNF1 pathway in yeast). The downstream effects depend heavily on the cell’s metabolic state.

In mammalian cells, metformin generally:

  • decreases ATP production,
  • activates AMPK,
  • suppresses mTOR signaling,
  • decreases de novo lipogenesis,
  • increases fatty acid oxidation,
  • reduces hepatic glucose production.

Because of these downstream effects, metformin often reduces lipid accumulation in obesity and type II diabetes.

However, those studies are almost always performed in metabolically unhealthy or nutrient-replete systems. Your experiment is asking a different question:What happens when the cell first experiences nutrient deprivation and is then refed? We know much less about this.

So, why might restricted cells accumulate more lipid: 1. Metabolic memory. After prolonged restriction, cells become metabolically programmed to conserve resources. So rather than investing carbon into new biomass, it diverts carbon into neutral lipid storage. 2. Growth and storage become uncoupled. Growth hardly changed.Nile Red changed substantially. That means metformin probably isn’t changing how much glucose the cells take up (which would lead to growth).Instead, it is changing where that carbon goes. 3. Nutrient signaling is different. Cells previously grown in 0.5% have higher SNF1, altered TOR, or different carbon reserve metabolism.

Considerations for moving forward:

  1. My recommendation, focus on the “how” part:
  • In previously restricted cells, does metformin increase lipid accumulation by increasing lipid synthesis/storage, decreasing lipid breakdown, or shifting carbon away from growth and into storage?
  • This would be done by running qPCR on storage/metabolism genes
  • Start by looking into these:
Category Genes
TAG/lipid storage DGA1, LRO1
Fatty acid synthesis ACC1
Lipid breakdown TGL3, TGL4
Energy sensing SNF1
Growth/nutrient signaling TOR1, SCH9
Carbohydrate storage GSY1/GSY2, TPS1/TPS2
  • Is the extra Nile Red signal due to increased lipid synthesis or decreased lipid utilization?
  • That determines the molecular direction.
  • If it’s increased synthesis, I’d examine genes like ACC1, DGA1, and LRO1.
  • If it’s decreased utilization, I’d focus on TGL3, TGL4, and β-oxidation pathways.
  1. Other options:
  • Do a time series of Nile Red (Measure the accumulation at 6h, 12h, 24h)
  • Recovery experiment: After 48h of refeeding, remove metforming and grow cells again at normal media. (Is the effect reversible)
  • Storage tradeoff experiment: Measure glycogen or trehalose. Are restricted cells storing carbon specifically as lipids, or generally as storage molecules.
  • Stress tolerance assay. After restriction/refeeding, expose cells to mild stress (peroxide, heat shock, salt) and see if metabolic history changes later stress resistance.