【问题标题】:How to dataframe that holds a list inside of a column into multiple columns in R?如何将包含列内列表的数据框转换为R中的多列?
【发布时间】:2019-04-11 17:39:17
【问题描述】:

我有一个名为坐标的列,它是每个地址的纬度和经度坐标的数据框。我想将列拆分为两列,称为 lat 和 long,而不是一列称为坐标

我有以下数据:

vsn                             address         coordinates
53 079 Ashland Ave & Elston Ave Chicago IL -87.66826, 41.91873
76 097     Pulaski Rd & 71st St Chicago IL -87.72242, 41.76412
84 0A3  Long Ave & Lawrence Ave Chicago IL -87.76257, 41.96759

坐标列包含一个列表 我需要将数据转换为以下内容:

vsn                             address        Lat       Lon  
53 079 Ashland Ave & Elston Ave Chicago IL -87.66826 41.91873
76 097     Pulaski Rd & 71st St Chicago IL -87.72242 41.76412
84 0A3  Long Ave & Lawrence Ave Chicago IL -87.76257 41.96759

我不知道如何提取数据,因为它是一个数据框,具体如下所示

列坐标的类型如下所示:

dput 的输出(数据$坐标)

structure(list(coordinates = list(c(-87.668257, 41.918733), c(-87.72242, 
41.764122), c(-87.76257, 41.96759))), row.names = c(53L, 76L, 
84L), class = "data.frame")

【问题讨论】:

  • 请在问题中显示 dput(DF) 的输出,其中 DF 是具有 3 列的输入数据框。
  • 我已经重新打开了这个。所谓的重复是为了分割一个字符串,但这个问题是关于分割一个列表。

标签: r


【解决方案1】:

由于输入数据未在问题中重复显示,因此存在一些问题,即coordinates 列是否实际上是问题中所述的列表,或者真正的意思是它是逗号分隔的列字符串。在最后的注释中,我们以可重复的方式展示了这两种情况,在这里我们展示了如何处理这两种情况:

坐标是一列字符串

library(dplyr)
library(tidyr)

DFstring %>%
  separate(coordinates, c("Lat", "Lon"), sep = ", ", convert = TRUE)

给予:

  vsn                             address       Lat      Lon
1 079 Ashland Ave & Elston Ave Chicago IL -87.66826 41.91873
2 097     Pulaski Rd & 71st St Chicago IL -87.72242 41.76412
3 0A3  Long Ave & Lawrence Ave Chicago IL -87.76257 41.96759

坐标列是一个列表

library(dplyr)

DFlist %>%
  rowwise %>%
  mutate(Lat = as.numeric(coordinates[1]), Lon = as.numeric(coordinates[2])) %>%
  ungroup %>%
  select(-coordinates)

给予:

# A tibble: 3 x 4
  vsn   address                               Lat   Lon
  <chr> <chr>                               <dbl> <dbl>
1 079   Ashland Ave & Elston Ave Chicago IL -87.7  41.9
2 097   Pulaski Rd & 71st St Chicago IL     -87.7  41.8
3 0A3   Long Ave & Lawrence Ave Chicago IL  -87.8  42.0

注意

Lines <- "vsn;address;coordinates
079;Ashland Ave & Elston Ave Chicago IL;-87.66826, 41.91873
097;Pulaski Rd & 71st St Chicago IL;-87.72242, 41.76412
0A3;Long Ave & Lawrence Ave Chicago IL;-87.76257, 41.96759"

DFstring <- read.table(text = Lines, header = TRUE, sep = ";", as.is = TRUE,
  strip.white = TRUE)

DFlist <- DFstring
DFlist$coordinates <- strsplit(DFstring$coordinates, ", ")

更新

请注意,上面已经发布的代码适用于添加到问题中的 dput 输出。

DF <-
structure(list(coordinates = list(c(-87.668257, 41.918733), c(-87.72242, 
41.764122), c(-87.76257, 41.96759))), row.names = c(53L, 76L, 
84L), class = "data.frame")

# same as code above except we use DF as the input
DF %>%
  rowwise %>%
  mutate(Lat = as.numeric(coordinates[1]), Lon = as.numeric(coordinates[2])) %>%
  ungroup %>%
  select(-coordinates)

给予:

# A tibble: 3 x 2
    Lat   Lon
  <dbl> <dbl>
1 -87.7  41.9
2 -87.7  41.8
3 -87.8  42.0

【讨论】:

  • 我收到以下错误,因为坐标列是列表错误:(列表)对象不能被强制输入'double'
  • 启动一个新的 R 实例,将注释中的代码复制并粘贴到其中,然后将代码复制并粘贴到答案正文中,您应该会得到与我得到的相同的结果。跨度>
  • 我现在更新了这个问题。类型不是我最初指定的类型。我的错。类型实际上是一个数据框,里面有一个列表
  • 更新我添加了 dput(data$coordinates) 的结果
  • 我发布的代码已经与问题中的 dput 输出一起使用,无需对其进行任何更改。请参阅更新。
【解决方案2】:

试试这个-

   > library(splitstackshape)
   > cSplit(dt,"Coordinates")

注意-此功能还可以帮助您在拆分时trim空格。

查看?cSplit 以获得更多帮助。

【讨论】:

    【解决方案3】:

    一种可能性:map_df() 分隔列,然后 cbind() 将结果添加到原始数据框。

    library(dplyr)
    library(purrr)
    
    # Example Data
    X <- data_frame(
        vsn = c(53, 76, 84),
        coordinates = map(1:3, ~ as.list(rnorm(2)))
    )
    
    # Create a new data frame from the list column
    purrr::map_df(X$coordinates, ~ data_frame(Lat = .x[[1]], Lon = .x[[2]]))
    
    # A tibble: 3 x 2
        Lat   Lon
      <dbl> <dbl>
    1 -1.03 1.45 
    2 -1.17 0.794
    3  2.06 0.646
    

    然后cbind()与原始数据框合并

    cbind(X, purrr::map_df(X$coordinates, ~ data_frame(Lat = .x[[1]], Lon = .x[[2]])))
    
      vsn           coordinates       Lat       Lon
    1  53   -1.034076, 1.451652 -1.034076 1.4516519
    2  76 -1.1738099, 0.7943916 -1.173810 0.7943916
    3  84  2.0586963, 0.6462277  2.058696 0.6462277
    

    【讨论】:

      【解决方案4】:

      我们可以使用separate

      > library(tidyverse)
          > dat %>% 
          separate(coordinates, c("Lat", "Lon"), sep=",") %>% 
          mutate(Lat = as.numeric(Lat),
                 Lon = as.numeric(Lon))
      # A tibble: 3 x 4
        vsn    address                               Lat   Lon
        <chr>  <chr>                               <dbl> <dbl>
      1 53 079 Ashland Ave & Elston Ave Chicago IL -87.7  41.9
      2 76 097 Pulaski Rd & 71st St Chicago IL     -87.7  41.8
      3 84 0A3 Long Ave & Lawrence Ave Chicago IL  -87.8  42.0
      

      更新

      鉴于您的问题版本,这里有一个 R 基础解决方案

      > out <- as.data.frame(do.call(rbind, dat$coordinates))
      > names(out) <- c("Lat", "Lon")
      > out
              Lat      Lon
      1 -87.66826 41.91873
      2 -87.72242 41.76412
      3 -87.76257 41.96759
      

      【讨论】:

      • 我得到这个结果:警告:预计 2 件。在 1 行 [1] 中丢弃的附加件。警告:强制引入的 NA 警告:强制引入的 NA vsn Lat Lon 1 079 NA NA 2 097 NA NA 3 0A3 NA NA
      猜你喜欢
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      • 2020-07-29
      • 1970-01-01
      • 2022-11-23
      • 1970-01-01
      • 1970-01-01
      • 2022-12-11
      相关资源
      最近更新 更多