【问题标题】:How to split each value using delimiter in each column for a specific row in a dataframe如何在数据框中的特定行的每一列中使用分隔符拆分每个值
【发布时间】:2020-09-19 00:22:38
【问题描述】:

我有一个数据框,其中存在错误的特定行,这意味着两行已合并为一个由空格指示的行。我有错误所在行的索引,并希望使用索引构建一个函数来简单地创建两个新列表,然后我可以将它们插入数据框(作为 2 行)并替换不正确的行.

我在 R 中有以下数据框(第 3 行是错误的):

   Location  V1  V2  V3  V4
1       nyc   2  20   9   2
2       bos   4   5   3   8
3 atl m dal 1 4 3 4 1 3 5 2
4       mia   3   1   8   4

structure(list(Location = c("nyc", "bos", "atl m dal", "mia"), 
    V1 = c("2", "4", "1 4", "3"), V2 = c("20", "5", "3 4", "1"
    ), V3 = c("9", "3", "1 3", "8"), V4 = c("2", "8", "5 2", 
    "4")), row.names = c(NA, 4L), class = "data.frame")

第 1 步:所需的输出将是两个列表/向量(对于每个错误行),如下所示:

atl m
1
3
1
5

dal 
4
4
3
2

第 2 步:拥有这些列表后,我应该能够将它们作为行插入/添加到现有数据框中(并删除错误行),如下所示:

  Location V1 V2 V3 V4
1      nyc  2 20  9  2
2      bos  4  5  3  8
3    atl m  1  3  1  5
4      dal  4  4  3  2
5      mia  3  1  8  4

主要是寻求第 1 步的帮助。除了第一列之外,所有列 (V1...V4) 都有一个空格,可以用作分隔每个值的分隔符,这使得它变得容易,但第一列 location 并不那么简单。我需要根据我可以匹配到的另一个列表手动为该列手动设置字符串的子集。

【问题讨论】:

  • 您可以使用dput(head(df)) 添加您的数据吗?你怎么知道有错误的行是 atl mdal ?你怎么知道这个位置叫dal,它不在数据中。
  • @RonakShah。抱歉 - 我修复了输入数据以反映这一点,并添加了 dput() 。而且我知道存在错误,因为每个数字列(v1 到 v4)中有两个数字值,由空格分隔。同样,我也可以判断,因为“atl m”和“dal”应该是单独的位置。为了给你更多的背景信息,我使用了一个图像抓取工具将表格从 PDF 转换为数据框,但该工具无法正确转换所有行,因此我需要一种解决方法来清理剩余的内容。

标签: r dataframe dplyr


【解决方案1】:

我们可以识别有错误的行,其中包含空格 (\\s)。创建此类行的单独数据框。获取location 并不简单,因为其中有很多空格。我使用的逻辑是最后一个词进入新行,而之前的所有内容都保持在同一行中。

最后,我们将这两个数据帧结合起来,得到一个完整的数据帧。

library(dplyr)
inds <- grep('\\s', df$V1)

tmp <- df[inds, ]

tmp %>%
  tidyr::separate_rows(everything(), sep = '(\\s)(?!.*\\s)') %>%
  bind_rows(df[-inds, ]) %>%
  type.convert(as.is = TRUE)

#  Location    V1    V2    V3    V4
#  <chr>    <int> <int> <int> <int>
#1 atl m        1     3     1     5
#2 dal          4     4     3     2
#3 nyc          2    20     9     2
#4 bos          4     5     3     8
#5 mia          3     1     8     4

【讨论】:

  • 简单并且将行分开!有没有办法用这种方法轻松保持行的顺序?自创建新数据框以来,它将首先按新创建的行排序,然后是原始行。如果我能够保持相同的行顺序,我可以轻松地覆盖Location,因为我有一个列表,列出了该列的正确顺序的值。
  • 要保持顺序,您可以添加行号列。 df &lt;- df %&gt;% mutate(row = row_number()) 然后使用上面的答案,最后使用arrange(row) 按排序顺序获取数据,如果不需要,删除row 列。
  • 有效!您只需将row 重铸为数字,因为当您使用separate_rows 时它会转换为字符
  • 是的..对。但我认为最好从separate_rows 中排除row,因为我们不想分离row 列。 tidyr::separate_rows(-row, sep = '(\\s)(?!.*\\s)') %&gt;% 这样可以避免数字转换。
【解决方案2】:

有点粗略,不过你可以直接复制问题行,将“”拆分的前半部分作为第一行(“atl m”),后半部分作为“dal”行:

tibble(df) %>%
  mutate(across(.fns = ~str_replace(., " \\w+$", ""))) %>%
  add_row(
    df %>% 
      slice(3) %>%
      mutate(across(.fns = ~str_replace(., "^.* (\\w+)$", "\\1")))
  )

# A tibble: 5 x 5
  Location V1    V2    V3    V4   
  <chr>    <chr> <chr> <chr> <chr>
1 nyc      2     20    9     2    
2 bos      4     5     3     8    
3 atl m    1     3     1     5    
4 mia      3     1     8     4    
5 dal      4     4     3     2    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    • 2019-02-25
    • 2017-06-24
    相关资源
    最近更新 更多