【问题标题】:Splitting several columns of a dataframe with 'separate' (tidyr) in R在 R 中使用“单独”(tidyr)拆分数据帧的几列
【发布时间】:2018-04-13 18:44:36
【问题描述】:

大家早上好,我已经阅读了几篇关于用 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技能很差!

有很多线程解释如何将一列分成两列,例如:Split a column of a data frame to multiple columns

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

非常感谢您的帮助,

一切顺利:)

【问题讨论】:

  • 您想要一个涉及separate 的解决方案或其他解决方案吗?
  • 任何建议都会非常有用,非常感谢 Amarchin :-)

标签: r dataframe split tidyr


【解决方案1】:

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

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

【讨论】:

  • 非常感谢安东尼奥,除了一个小问题外,这一切都很好:我的基因型中有时会缺少值,编码为 (对不起,我应该在之前提到过),并且似乎该命令无法将它们拆分为两个新的 值。我也很好奇:命令如何知道它必须根据“/”分割主要值:)?再次感谢您!
  • 您可以看到该命令知道使用任何非字母数字值进行拆分。在这里查看:rdrr.io/cran/tidyr/man/separate.html,或输入?separate
  • 谢谢安东尼奥,我将用“00/00”替换我的 NA 值并查看您的链接!最好的问候,克里斯
  • 是的,这行得通。我遵循相同的方法(即替换为“NA/NA”)。我做了一个小而有用的改变。我在separate 命令中添加了convert = .,这将使新列成为数字,如果您将其设置为T,则了解您的数值。在这种情况下,您将失去值前面的零。
  • 太棒了 :-) 这正是我所需要的,非常感谢您的帮助!祝你有美好的一天,克里斯
【解决方案2】:

您也可以使用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

【讨论】:

    猜你喜欢
    • 2017-08-12
    • 1970-01-01
    • 2016-05-17
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多