在 R 中使用“单独”(tidyr)拆分数据帧的几列

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

大家早上好,我已经阅读了一些有关使用 R 进行列拆分的内容,但我找不到如何解决我的情况。

我想使用 tidyr R 包中的“单独”函数根据分隔符将数据帧的列分成两列。

我有这个数据框:


dat1
    AIN5997 AIN7452 AIN8674 AIN9655
001   01/02   02/02   02/02   01/02
002   01/02   01/01   02/02   02/02
003   01/02   01/02   01/01   02/02
004   01/02   01/01   02/02   01/02
005   01/01   01/01   02/02   02/02
006   01/02   01/02   01/01   02/02
...

我想根据“/”将每一列分成两部分,如果可能的话,同时保留列名称(例如:AIN5997 将变为 AIN5997.1 和 AIN5997.2)

我认为“单独”是可能的,但在尝试“应用”时,我无法将过程扩展到框架的每一列(可能是因为单独一次适用于数据帧和单个列)。这实际上一定很简单,但我的 R 技能很差!

有很多线程解释如何将一列拆分为两列,例如:将数据帧的一列拆分为多列

但我找不到如何同时扩展多个列的过程。

非常感谢您的帮助,

祝一切顺利:)

r dataframe split tidyr
3个回答
3
投票

诀窍是按正确的顺序创建新名称,因此请确保提前对要分隔的列进行排序。

NA
值的问题在于该过程无法拆分它们。所以,诀窍是用可以拆分的东西替换它们。检查一下:

library(dplyr)
library(tidyr)

# example dataset
dt = data.frame(id = 1:2,
                AIN5997  = c("01/02", "01/02"),
                AIN7452  = c("02/02", NA),
                AIN8674 = c("02/02","02/02"), stringsAsFactors = F)

# specify columns you want to separate (specify column positions)
input_names = names(dt)[2:4]

# create new names (you want each name twice)
new_names = expand.grid(input_names, 1:2) %>% 
  unite(v, Var1, Var2, sep=".") %>% 
  pull(v) %>% 
  sort()

dt %>%
  unite_("v", input_names) %>%                  # unite columns of interest
  mutate(v = gsub("NA", "NA/NA", v)) %>%        # replace NAs with something that can be separated
  separate(v, new_names, convert = F)           # separate elements and give new names

#   id AIN5997.1 AIN5997.2 AIN7452.1 AIN7452.2 AIN8674.1 AIN8674.2
# 1  1        01        02        02        02        02        02
# 2  2        01        02        NA        NA        02        02

我还添加了更好的解决方案。它会自动处理

NA
值,您不必担心列名称及其顺序。

library(dplyr)
library(tidyr)
library(purrr)

# example dataset
dt = data.frame(id = 1:2,
                AIN5997  = c("01/02", "01/02"),
                AIN7452  = c("02/02", NA),
                AIN8674 = c("02/02","02/02"), stringsAsFactors = F)

# separate a given column of your initial dataset
f = function(x) { dt %>% select_("id", x) %>% separate_(x, paste0(x, c(".1",".2"))) }


names(dt)[2:4] %>%             # get names of columns you want to separate
  map(f) %>%                   # apply the function above to each name (will create a list of dataframes)
  reduce(left_join, by="id")   # join dataframes iteratively

#   id AIN5997.1 AIN5997.2 AIN7452.1 AIN7452.2 AIN8674.1 AIN8674.2
# 1  1        01        02        02        02        02        02
# 2  2        01        02      <NA>      <NA>        02        02

1
投票

您还可以使用

tstrsplit()

# example dataset
df <- data.frame(AIN5997  = c("01/02", "01/02"),
                 AIN7452  = c("02/02","01/01"),
                 AIN8674 = c("02/02","02/02"), stringsAsFactors = F)
df
df2 <- as.data.frame(unlist(lapply(df, data.table::tstrsplit, "/"),
                            recursive = FALSE))
df2
colnames(df2) # change colnames
colnames(df2) <- paste(substr(colnames(df2), 1, nchar(colnames(df2))-1),
                       substr(colnames(df2), nchar(colnames(df2)), nchar(colnames(df2))),
                       sep = ".")
df2

0
投票

tidyr
中的新功能正是为了这个目的

dt = data.frame(id = 1:2,
                AIN5997  = c("01/02", "01/02"),
                AIN7452  = c("02/02", NA),
                AIN8674 = c("02/02","02/02"), stringsAsFactors = F)
library(tidyr)
dt %>% 
  separate_wider_delim(-id, delim = "/", names_sep = ".")
#> # A tibble: 2 × 7
#>      id AIN5997.1 AIN5997.2 AIN7452.1 AIN7452.2 AIN8674.1 AIN8674.2
#>   <int> <chr>     <chr>     <chr>     <chr>     <chr>     <chr>    
#> 1     1 01        02        02        02        02        02       
#> 2     2 01        02        <NA>      <NA>      02        02

创建于 2024-04-21,使用 reprex v2.1.0

© www.soinside.com 2019 - 2024. All rights reserved.