【问题标题】:Splitting data on data.frame column在 data.frame 列上拆分数据
【发布时间】:2021-07-18 14:52:47
【问题描述】:

我目前正在开展一个项目,我正在尝试计算各种数据,但是,我正在使用的 CSV 文件在列中有异常。它包含格式为“%d/%m/%y”的日期,后跟一个字符串。

这在整个列中重复(列是无标题的,以防万一),我目前试图实现的是将整个列中的日期替换为只保留剩余的字符串。

我目前的做法是使用 gsub 函数,如下所示:

gsub(".[/]|[/]|[[:digit:]].", " ", dataset column)

这似乎最初可以工作,但是在运行 head 命令时,它似乎仅将其应用于前 6-7 个字段,其余字段显示为 NA 值。

如果我正在处理包含 3000 多个条目的列,或者实现此目的的代码背后的逻辑有问题,那么 GSub 函数是否有任何限制。

这里是用于代码的示例数据:

structure(list(V1 = c("3/3/2005Mitsubishi", "3/4/2006Jaguar", 
"13/2/2007Land Rover", "12/12/2009Ferrari", "4/4/2008Jeep", "3/3/2005Honda"
), V2 = c("Mitsubish", "Jaguar", "Land Rover", "Ferrari", "Jeep", 
"Honda")), row.names = c(NA, 6L), class = "data.frame")

【问题讨论】:

  • 请与dput(head(data))分享您的数据的可重现样本。
  • 感谢您的快速回复。这是dput(head(data))structure(list(V1 = c("3/3/2005Mitsubishi", "3/4/2006Jaguar", "13/2/2007Land Rover", "12/12/2009Ferrari", "4/4/2008Jeep", "3/3/2005Honda" ), V2 = c("Mitsubish", "Jaguar", "Land Rover", "Ferrari", "Jeep", "Honda")), row.names = c(NA, 6L), class = "data.frame")的数据输出

标签: r dataframe analytics


【解决方案1】:

如果您想保留所有三列。请记住,我们定义了两个捕获组,一个捕获日期,另一个捕获其余组。因此,在tidyr::extractregex 参数中,我们定义了如何根据我们定义的捕获组来分隔字符串并放入尽可能多的列中:

library(tidyr)

df %>%
  extract(V1, c("V1", "V3"), "(\\d+\\/\\d+\\/\\d+)(.*)")

          V1         V3         V2
1   3/3/2005 Mitsubishi  Mitsubish
2   3/4/2006     Jaguar     Jaguar
3  13/2/2007 Land Rover Land Rover
4 12/12/2009    Ferrari    Ferrari
5   4/4/2008       Jeep       Jeep
6   3/3/2005      Honda      Honda

如果您想分隔多列,一种方法是编写自定义函数并使用数据字符串组合应用于每一列:

library(rlang)

fn <- function(...) {
  dots <- dots_list(...)
  extract(..., into = sprintf("%s_col_%d", dots[[2]], 1:2), regex = "(\\d+\\/\\d+\\/\\d+)(.*)")
}

# Now imagine we have a data set called df2 which has two columns we 
# would like to separate

df %>%
  mutate(V3 = V1) %>%
  select(V1, V3) -> df2

                   V1                  V3
1  3/3/2005Mitsubishi  3/3/2005Mitsubishi
2      3/4/2006Jaguar      3/4/2006Jaguar
3 13/2/2007Land Rover 13/2/2007Land Rover
4   12/12/2009Ferrari   12/12/2009Ferrari
5        4/4/2008Jeep        4/4/2008Jeep
6       3/3/2005Honda       3/3/2005Honda

然后我们将它应用于我们的数据集,只选择我们想要分离的列:

# Instead of `names(df2)` you can choose a character vector containing the
# name of the columns you would like to separate

library(purrr)
names(df2) %>%
  reduce(~ fn(.x, .y), .init = df2)

    V1_col_1   V1_col_2   V3_col_1   V3_col_2
1   3/3/2005 Mitsubishi   3/3/2005 Mitsubishi
2   3/4/2006     Jaguar   3/4/2006     Jaguar
3  13/2/2007 Land Rover  13/2/2007 Land Rover
4 12/12/2009    Ferrari 12/12/2009    Ferrari
5   4/4/2008       Jeep   4/4/2008       Jeep
6   3/3/2005      Honda   3/3/2005      Honda

我发现 post 对此解决方案非常有帮助。

【讨论】:

  • 谢谢!这是一个方便的方法。您知道有什么方法可以从根本上清理数据并从数据集中完全删除日期吗?在上面的结果中,日期现在被存储为一个独立的列,但是,目的是完全删除日期,只保留例如。三菱、捷豹等。提前致谢
  • 我首先怀疑这一点,但认为在这种情况下,我们最终会得到 2 个完全相同的变量。所以您只想删除日期并保留其余日期?
  • 没错。最终目标是清理第一列,因此只剩下字符串部分和完整的删除日期。为混乱道歉。
  • 太棒了。这确实是删除日期的正确技巧。而且我假设在您想要保留所有 3 个的情况下,您需要修改变异代码以捕获并显示日期,对吗?按照df %&gt;% mutate(V1 = gsub("(\\d+\\/\\d+\\/\\d+)(.*)", "\\1,"\\2", V1))的思路思考
  • 感谢@jay.sf。这两种解决方案都非常有用并产生了正确的结果,再次感谢。关于这个的一个问题 - 这种方法可以外推到更大的数据集(更多列)还是这只适用于这个特定数量的列(即 2) 问的原因是我现在已经添加了带有字符串的额外列(大约 30 额外具有单个字符串的列)并运行上述内容会在以前正确显示的位置呈现 NA 值。
【解决方案2】:

strsplit 在(模拟的)后视。

r <- data.frame(do.call(rbind, 
                        strsplit(dat[, 1], '\\d{4}\\K', perl=TRUE)), dat[-1])
r[, 1] <- as.Date(r[, 1], '%D')  ## transform the date
r
#           X1         X2         V2
# 1 2003-03-20 Mitsubishi  Mitsubish
# 2 2003-04-20     Jaguar     Jaguar
# 3 2013-02-20 Land Rover Land Rover
# 4 2012-12-20    Ferrari    Ferrari
# 5 2004-04-20       Jeep       Jeep
# 6 2003-03-20      Honda      Honda

This answer 很好地解释了\K

编辑

如果您不需要日期,或者省略“转换日期”步骤,然后执行r &lt;- r[-1]


数据:

dat <- structure(list(V1 = c("3/3/2005Mitsubishi", "3/4/2006Jaguar", 
"13/2/2007Land Rover", "12/12/2009Ferrari", "4/4/2008Jeep", "3/3/2005Honda"
), V2 = c("Mitsubish", "Jaguar", "Land Rover", "Ferrari", "Jeep", 
"Honda")), row.names = c(NA, 6L), class = "data.frame")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多