如何使用 R 将同一 Excel 文件中的列合并为单个列?

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

我目前有一个 Excel 文档,简化后如下所示:

   A1   A2   B1   B2    B3   C1   C2   ...   H12
   1    5    11   14    15   19   22   ...   ...
   2    6    12         16   20   23
   3    7    13         17   21   24
   4    8               18        25
        9                         26
        10                        27

我必须以两种不同的方式组合列以获得两个不同的结果文档。 首先,我必须以将所有仅包含数字 1 的列组合在一起的方式组合列,这将产生如下所示的文档:

   Column 1   Column 2   Column 3   ...   Column 12 
   1          5          15         ...   ...
   2          6          16
   3          7          17
   4          8          18
   11         9
   12         10
   13         14
   19         22
   20         23
   21         24
              25
              26
              27

对于第二种方式,我需要以一种将所有以相同数字开头的原始列合并为一列的方式来组合列,例如:

   Column A   Column B   Column C   ...   Column H
   1          11         19         ...   ...
   2          12         20
   3          13         21
   4          14         22
   5          15         23
   6          16         24
   7          17         25
   8          18         26
   9                     27
   10

要转换的文件的标头编号为从 A1 到 H12。这意味着第一个生成的文档最终应有 12 列,第二个文档应有 8 列。

我已经尝试过用

rbind
这样做,但我没能做到。

有人可以帮我解决这个问题吗?

提前非常感谢您!

r excel tidyverse multiple-columns reshape2
2个回答
0
投票

听起来您阅读 Excel 没有问题,所以我假设您只是将整个工作表读入 data.frame

table
。您可以使用
tidyr::pivot_longer
获取数据框,其中一个条目中存在对行标题的引用,而另一个条目中存在对值的引用:

table <- pivot_longer(table, cols = names(table), values_drop_na = TRUE)

然后您可以使用

substring
创建两个带有数字和字母的附加列:

table$number <- substring(table$name, 2)
table$letter <- substring(table$name, 1, 1)

写可以分两个for循环完成:(我用

openxlsx

byNumbers <- buildWorkbook("")
for(i in 1:12){
  vec <- c(i, filter(table, number == i)$value)
  writeData(wb = byNumbers, sheet = 1, x = vec, startCol = i)
}

byLetter <- buildWorkbook("")
for(i in 1:8){ # H is the 8th letter
  iLet <- LETTERS[i]
  vec <- c(iLet, filter(table, letter == iLet)$value)
  writeData(wb = byLetter, sheet = 1, x = vec, startCol = i)
}

然后您可以保存两个工作簿。

希望这有帮助!


0
投票

肯定有更优雅的方法,但是如果不知道标题或数据在现实中是什么样子,这将是一个相对没有魔法的路径:

代码

将数据放入长格式

library(tidyverse)
# Put data.frame into long format
df_long <- df %>%
    # Put data into long format
    gather(key, val) %>%  #you could also use pivot_longer()
    drop_na() %>%
    # Separate letters and numbers
    separate(key, c("letter", "number"), sep = "(?=[0-9]{1,2}$)") %>%
    # Sort
    arrange(letter, number) 

# Result
> head(df_long)
  letter number val
1      A      1   1
2      A      1   2
3      A      1   3
4      A      1   4
5      A      2   5
6      A      2   6
... 

生成字母表

# By letters
df_letters <- df_long %>%
    # Drop number col
    select(-number) %>%
    # Add rolling ID
    group_by(letter) %>%
    mutate(id = row_number()) %>%
    ungroup() %>%
    # Spread into wide format
    pivot_wider(
        id_cols = id, names_from = letter, names_prefix = "Column_", values_from = val
    ) %>%
    select(-id)

# Result

df_letters
# A tibble: 10 × 3
   Column_A Column_B Column_C
      <int>    <int>    <int>
 1        1       11       19
 2        2       12       20
 3        3       13       21
 4        4       14       22
 5        5       15       23
 6        6       16       24
 7        7       17       25
 8        8       18       26
 9        9       NA       27
10       10       NA       NA

生成数字表

# By numbers
df_numbers <- df_long %>%
    # Drop letter col
    select(-letter) %>%
    # Add rolling ID
    group_by(number) %>%
    mutate(id = row_number()) %>%
    ungroup() %>%
    # Spread into wide format
    pivot_wider(
        id_cols = id, names_from = number, names_prefix = "Column_", values_from = val
    ) %>%
    # Drop ID col
    select(-id)

# Result
> df_numbers
# A tibble: 13 × 3
   Column_1 Column_2 Column_3
      <int>    <int>    <int>
 1        1        5       15
 2        2        6       16
 3        3        7       17
 4        4        8       18
 5       11        9       NA
 6       12       10       NA
 7       13       14       NA
 8       19       22       NA
 9       20       23       NA
10       21       24       NA
11       NA       25       NA
12       NA       26       NA
13       NA       27       NA


数据

df <- structure(list(A1=c(1L,2L,3L,4L,NA,NA),A2=5:10,B1=c(11L,12L,13L,NA,NA,NA),B2=c(14L,NA,NA,NA,NA,NA),B3=c(15L,16L,17L,18L,NA,NA),C1=c(19L,20L,21L,NA,NA,NA),C2=22:27),row.names=c(NA,-6L),class=c("data.table","data.frame"))
© www.soinside.com 2019 - 2024. All rights reserved.