【问题标题】:how do you convert factor into data frame你如何将因子转换为数据框
【发布时间】:2020-10-21 14:14:51
【问题描述】:

如何将以下因子转换为数据框?

dput(d)
structure(1L, .Label = "c(\"CONTEXTLESS\", \"CONTEXTLESS\", \"CONTEXTLESS\", \"CONTEXTLESS\", \"CONTEXTLESS\", \"CONTEXTLESS\", \"CONTEXTLESS\", \"CONTEXTLESS\"), c(\"app1\", \"client\", \"org\", \"app1\", \"DATA_CENTER\", \"PURPOSE\", \"REGION\", \"Test\"), c(NA, \"NONE\", \"Host:Environment:test123\", \"111\", \"222\", \"GENERAL\", \"444\", \"555\")", class = "factor")


> d
[1] c("CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS"), c("app1", "client", "org", "app1", "DATA_CENTER", "PURPOSE", "REGION", "Test"), c(NA, "NONE", "Host:Environment:test123", "111", "222", "GENERAL", "444", "555")
Levels: c("CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS", "CONTEXTLESS"), c("app1", "client", "org", "app1", "DATA_CENTER", "PURPOSE", "REGION", "Test"), c(NA, "NONE", "Host:Environment:test123", "111", "222", "GENERAL", "444", "555")

【问题讨论】:

  • as.data.frame(d) 没用?
  • @RicardoSemiãoeCastro,它把外放放在 c("") 中。我需要每个向量都在行中
  • 你能发一张d 的照片而不是dput 吗?我不明白你的数据格式
  • @RicardoSemiãoeCastro,好的,我也放了d的输出。

标签: r


【解决方案1】:

也许试试这个,让我知道这是否适合你。您可以连贯为字符,然后为字符串放置一个通用分隔符。代码如下:

#Code
d1 <- as.character(d)
d1 <- gsub(', c','*c',d1)
d1 <- strsplit(d1,split='\\*')
df <- as.data.frame(do.call(cbind,d1))

df 的输出将如下所示:

在一些新的细节之后,尝试使用tidyverse 在清理后分隔行:

library(tidyverse)
#Code
d1 <- as.character(d)
d1 <- gsub(', c','*c',d1)
d1 <- strsplit(d1,split='\\*')
df <- as.data.frame(do.call(cbind,d1),stringsAsFactors = F)
#Clean
df$V1 <- gsub('\"','',df$V1)
df$V1 <- gsub("c(","",df$V1,fixed=T)
df$V1 <- gsub(")","",df$V1)
#Format
newdf <- df %>% mutate(id=row_number()) %>%
  separate_rows(V1,sep = ',') %>%
  mutate(V1=trimws(V1)) %>%
  group_by(id) %>% mutate(Var=paste0('Var.',row_number())) %>%
  pivot_wider(names_from = Var,values_from=V1)

输出:

# A tibble: 3 x 9
# Groups:   id [3]
     id Var.1      Var.2      Var.3               Var.4     Var.5     Var.6     Var.7     Var.8    
  <int> <chr>      <chr>      <chr>               <chr>     <chr>     <chr>     <chr>     <chr>    
1     1 CONTEXTLE~ CONTEXTLE~ CONTEXTLESS         CONTEXTL~ CONTEXTL~ CONTEXTL~ CONTEXTL~ CONTEXTL~
2     2 app1       client     org                 app1      DATA_CEN~ PURPOSE   REGION    Test     
3     3 NA         NONE       Host:Environment:t~ 111       222       GENERAL   444       555      

【讨论】:

  • 不,这行不通。我需要每个值都在自己的单元格上
  • @user1471980 你想要一个长向量或单元格中的每个值?
  • 单元格中的每个值。在这种情况下,应该有 3 行 8 列。
  • 快速提问。我会将其应用于大型数据集。我希望每个 c("") 有 8 个值,如果不是 8 个,有没有办法插入 "NA"?
  • @user1471980 因为我们正在使用pivot_wider(),所以函数理解这一点并在没有值的地方添加NA
【解决方案2】:

如果您从 Duck 的前三行代码开始,则可以解析它(显然)是 deparse()-d 的 R 代码来自:

#Code
d1 <- as.character(d)
d1 <- gsub(', c','*c',d1)
d1 <- strsplit(d1,split='\\*')
d1[[1]][2]
#[1] "c(\"app1\", \"client\", \"org\", \"app1\", \"DATA_CENTER\", \"PURPOSE\", \"REGION\", \"Test\")"

如果您使用lapply 串行应用eval(parse(text=.)-函数,那么您会返回一个可以强制转换为您的 cmets 建议您想要的长格式数据帧的对象:

setNames(lapply(d1[[1]], function(x) eval(parse(text=x))),paste0("V", 1:3))

$V1
[1] "CONTEXTLESS" "CONTEXTLESS" "CONTEXTLESS" "CONTEXTLESS" "CONTEXTLESS" "CONTEXTLESS"
[7] "CONTEXTLESS" "CONTEXTLESS"

$V2
[1] "app1"        "client"      "org"         "app1"        "DATA_CENTER" "PURPOSE"    
[7] "REGION"      "Test"       

$V3
[1] NA                         "NONE"                     "Host:Environment:test123"
[4] "111"                      "222"                      "GENERAL"                 
[7] "444"                      "555"   

因此:

> d2 <- setNames(lapply(d1[[1]], function(x) eval(parse(text=x))),paste0("V", 1:3))
> data.frame( d2[2:3])
           V2                       V3
1        app1                     <NA>
2      client                     NONE
3         org Host:Environment:test123
4        app1                      111
5 DATA_CENTER                      222
6     PURPOSE                  GENERAL
7      REGION                      444
8        Test                      555

【讨论】:

    【解决方案3】:

    只需 parseeval data.frame(...) 中的文本。无需重新发明轮子。

    df <- eval(parse(text = paste0("data.frame(", as.character(d), ")")))
    names(df) <- paste0("v", seq_along(df))
    

    输出

               v1          v2                       v3
    1 CONTEXTLESS        app1                     <NA>
    2 CONTEXTLESS      client                     NONE
    3 CONTEXTLESS         org Host:Environment:test123
    4 CONTEXTLESS        app1                      111
    5 CONTEXTLESS DATA_CENTER                      222
    6 CONTEXTLESS     PURPOSE                  GENERAL
    7 CONTEXTLESS      REGION                      444
    8 CONTEXTLESS        Test                      555
    

    【讨论】:

      【解决方案4】:

      我们可以使用str_match_all提取c(....)之间的所有内容,用逗号分割字符串并绑定数据集。

      do.call(rbind, lapply(stringr::str_match_all(d, 'c\\((.*?)\\)'), function(x) {
        do.call(rbind, strsplit(gsub('"', '',x[, 2]), ',\\s*'))
      }))
      

      【讨论】:

      • 当我这样做时,它只抓取数据集中的第一行。我有一千行。
      • 此行仅捕获 d 中的第一行,我需要将其应用于整个数据集 "data
      • @user1471980 是的,我使用了[[1]] 部分,因为d 的长度为1。如果您有大量数据,我们可以使用lapply/sapply 从每个列表中提取第二列。查看更新的答案。
      猜你喜欢
      • 2016-11-03
      • 1970-01-01
      • 1970-01-01
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 2018-01-12
      • 1970-01-01
      • 2012-11-16
      相关资源
      最近更新 更多