R - 将 CSV 文件从独特格式转换为标准数据帧

问题描述 投票:0回答:1

我早些时候曾问过这个问题,但今天正在调整问题以提供清晰度。

我正在编写一个需要治疗、受试者、体重和日期变量的脚本。 截至目前,此处链接的数据是我需要使用的格式。请注意,此处每个测量的主题和日期都是唯一的。我主要感兴趣的是稍后使用“body_mass_g”进行建模,以了解上下文。

   exp cohort    sbj treatment     date time body_mass_g food_weight_g blood_glucose_mgdl
1  dtx   tx03 dtx001      A    1/7/2020   NA       30.70            NA                 NA
2  dtx   tx03 dtx002      B    1/7/2020   NA       30.67            NA                 NA
3  dtx   tx03 dtx006      A    1/7/2020   NA       28.93            NA                 NA
4  dtx   tx03 dtx007      A    1/7/2020   NA       28.73            NA                 NA
5  dtx   tx03 dtx008      B    1/7/2020   NA       25.56            NA                 NA
6  dtx   tx03 dtx009      B    1/7/2020   NA       24.79            NA                 NA
7  dtx   tx03 dtx010      A    1/7/2020   NA       27.13            NA                 NA
8  dtx   tx03 dtx011      B    1/7/2020   NA       27.32            NA                 NA
9  dtx   tx03 dtx012      B    1/7/2020   NA       27.28            NA                 NA
10 dtx   tx03 dtx013      B    1/7/2020   NA       29.56            NA                 NA

但是,我目前的问题是一种新格式的csv文件数据,我需要将其转换为上述格式。新格式如下所示。 R 以一种非常混乱的方式解释我的新数据,因此我在下面附上了示例代码。日期列包含带有 body_mass_g(我感兴趣的变量)的嵌套子列。这不会在一列中显示日期,而是显示为具有嵌套列的大块,延伸到主题和治疗的每一行。还有更多日期向右延伸。仅供参考,我还可以在下面的数据之后攻击图像。

                       |   1/1/2023, Monday Day 0  |   1/2/2023, Tuesday Day 1  
1 Tag  sbj.  Treatment |  body_mass_g   BG  Hopper |  body_mass_g   BG  Hopper
2 10   1     A         |  22            1   6      |  22            1   6
3 12   2     B         |  21            3   5      |  21            3   5
4 12   2     A         |  11            3   7      |  11            3   7
5 13   1     B         |  33            2   8      |  33            2   8
6 12   2     A         |  44            1   9      |  44            1   9

显示我真正的新数据集的图像:https://i.stack.imgur.com/7BYV9.png

我真的只是尝试使用“read.csv”导入它,但不知何故,R 以一种极其奇怪的格式导入它,创建新列并将“X”添加到每个列标题上。由于它首先创建数据帧的格式很奇怪,我陷入了这个阶段。

我将不胜感激任何帮助。如果我可以提供更多信息,请告诉我。谢谢你。

r import transform
1个回答
0
投票

从 XLSX 文件中读取数据时可以跳过第一行, 将第一行值与列名称粘贴在一起。然后,您可以旋转 将数据转换为所需的格式并提取日期列。

下面的代码应该适用于您的数据。只需替换文件名即可 与您的文件名。

首先,我创建一个与您的结构相似的 Excel 文件:

library(openxlsx)
     
df1 <-
  data.frame(
    id = 1:10,
    body_mass_g = 11:20,
    BG = 21:30,
    Hopper = 1:10,
    body_mass_g = 11:20,
    BG = 21:30,
    Hopper = 1:10,
    check.names = FALSE
  )

first_colname_row <-
  c("", "1/1/2023, Monday Day 0", "", "", "1/2/2023, Monday Day 1") |>
  matrix(nrow = 1)

wb <- createWorkbook()

addWorksheet(wb, "sheet1")
writeData(wb, "sheet1", df1, startRow = 2)
writeData(wb, "sheet1", first_colname_row, colNames = FALSE)
mergeCells(wb, "sheet1", 2:4, 1)
mergeCells(wb, "sheet1", 5:7, 1)
saveWorkbook(wb, "merged_header_cells.xlsx", overwrite = TRUE)

这是适合您的相关代码:

library(tidyverse)
library(readxl)

file_name <- "merged_header_cells.xlsx"

# Read the data, skipping the first row
df2 <- read_excel(file_name, sheet = 1, skip = 1)

# Extract the first row and manipulate it to combine it with the
# column names.
col_name_groups <-
  read_excel(file_name, sheet = 1, col_names = FALSE) |>
  slice(1) |>
  pivot_longer(everything()) |>
  fill(value) |>
  replace_na(list(value = "")) |>
  pull(value)

# Clean up column names
col_names <-
  names(df2) |>
  str_remove("\\.\\.\\.[0-9]")

# Combine first and second rows of column names
col_names <-
  paste(col_name_groups, col_names, sep = "#") |>
  str_remove("^#")

# Apply combined column names, pivot data and extract the date column
df2 |>
  set_names(col_names) |>
  pivot_longer(-id,
               names_to = c("group", "var"),
               names_sep = "#") |>
  pivot_wider(names_from = var,
              values_from = value) |>
  mutate(date = str_extract(group, "(.*)(,)", group = 1)) |> 
  select(id, date, body_mass_g, BG, Hopper)
#> # A tibble: 20 × 5
#>       id date     body_mass_g    BG Hopper
#>    <dbl> <chr>          <dbl> <dbl>  <dbl>
#>  1     1 1/1/2023          11    21      1
#>  2     1 1/2/2023          11    21      1
#>  3     2 1/1/2023          12    22      2
#>  4     2 1/2/2023          12    22      2
#>  5     3 1/1/2023          13    23      3
#>  6     3 1/2/2023          13    23      3
#>  7     4 1/1/2023          14    24      4
#>  8     4 1/2/2023          14    24      4
#>  9     5 1/1/2023          15    25      5
#> 10     5 1/2/2023          15    25      5
#> 11     6 1/1/2023          16    26      6
#> 12     6 1/2/2023          16    26      6
#> 13     7 1/1/2023          17    27      7
#> 14     7 1/2/2023          17    27      7
#> 15     8 1/1/2023          18    28      8
#> 16     8 1/2/2023          18    28      8
#> 17     9 1/1/2023          19    29      9
#> 18     9 1/2/2023          19    29      9
#> 19    10 1/1/2023          20    30     10
#> 20    10 1/2/2023          20    30     10
© www.soinside.com 2019 - 2024. All rights reserved.