【问题标题】:Convert data frame of values into binary data frame where each unique value is a column将值的数据框转换为二进制数据框,其中每个唯一值都是一列
【发布时间】:2016-07-30 03:23:30
【问题描述】:

我正在从 csv 文件中读取数据,其中每一行都包含一些单独的字符串:

例如

data.csv ->
    x,f,t,h,b,g
    d,g,h
    g,h,a,s,d
    f
    q,w,e,r,t,y,u,i,o

data <- read.csv("data.csv", header = FALSE)

我想将此输入转换为数据框,其中列是输入中存在的唯一字符串集。在这种情况下,列将是字符串集{x,f,t,h,b,g,d,a,s,q,w,e,r,y,u,i,o}。此外,新数据框应为输入数据框中的每一行包含一行,这样如果列的名称存在于输入数据框中的该行中,则该列将具有值 1,或者如果该输入行中不存在列的名称。

在本例中,所需的输出如下:

    x f t h b g d a s q w e r y u i o
   ----------------------------------
1 | 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
2 | 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0
3 | 0 0 0 1 0 1 1 1 1 0 0 0 0 0 0 0 0
4 | 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 | 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1

下面的代码是我目前拥有的。但是,输出 df 最终成为一个数据框,其中包含正确的列,但 0 行。

我在 R 方面非常缺乏经验,这是我尝试组合一些可行的东西。在调用apply() 之前,它似乎按预期工作,这出乎意料地没有向df 添加任何内容。

data <- read.csv("data.csv", header = FALSE)

columnNames = c()
for (row in data) {
  for (eventName in row) {
    if (!(eventName %in% columnNames)) {
      columnNames = c(columnNames, eventName)
    }
  }
}
columnNames = t(columnNames)

df = data.frame(columnNames)
colnames(df) = columnNames
df = df[-1,]

apply(data, 1, function(row, df) {
  dat = data.frame(columnNames)
  colnames(dat) = columnNames
  dat = dat[-1,]

  for (eventName in row) {
    if (eventName != "") {
      dat[1,eventName] = 1
    }
  }

  df = rbind(df, dat)
}, df)

脚本完成后,它告诉我有以下两种形式的许多警告:

9: In `[<-.factor`(`*tmp*`, iseq, value = 1) : invalid factor level, NA generated
10: In `[<-.factor`(`*tmp*`, iseq, value = 1) :
  invalid factor level, NA generated

【问题讨论】:

  • 请使用dput 显示数据集。您的输入令人困惑。
  • 我只是表明输入是一个标准的逗号分隔的 csv 文件,由read.csv转换
  • 好的,如果所有这些都是单个字符串,我就更新了帖子。

标签: r dataframe apply data-extraction


【解决方案1】:

我们可以在splitting 列, 之后使用mtabulate

library(qdapTools)
mtabulate(strsplit(as.character(df1[,1]), ","))

base R方法split,列,将list输出的名称设置为行序列,将list转换为data.framestack) ,将'values'列更改为factor并指定levels,然后使用table获取频率。

table(transform(stack(setNames(strsplit(as.character(df1[,1]), ","), 1:nrow(df1)))[2:1], 
           values = factor(values, levels = unique(values))))
# 
#    x f t h b g d a s q w e r y u i o
#  1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
#  2 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0
#  3 0 0 0 1 0 1 1 1 1 0 0 0 0 0 0 0 0
#  4 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#  5 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1

更新

如果不是单列,

mtabulate(apply(df2, 1, FUN = function(x) x[x!=""]))

或者

as.data.frame.matrix(table(transform(stack(setNames(apply(df2, 1, 
     FUN = function(x) x[x!=""]), 
           1:nrow(df2)))[2:1],  values = factor(values, levels = unique(values)))))
#    
#    x f t h b g d a s q w e r y u i o
#  1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
#  2 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0
#  3 0 0 0 1 0 1 1 1 1 0 0 0 0 0 0 0 0
#  4 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#  5 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1

数据

df1 <- structure(list(V1 = c("x,f,t,h,b,g", "d,g,h", "g,h,a,s,d", "f", 
"q,w,e,r,t,y,u,i,o")), .Names = "V1", class = "data.frame", 
row.names = c(NA, -5L))

df2 <- structure(list(v1 = c("x", "d", "g", "f", "q"), v2 = c("f", "g", 
"h", "", "w"), v3 = c("t", "h", "a", "", "e"), v4 = c("h", "", 
"s", "", "r"), v5 = c("b", "", "d", "", "t"), v6 = c("g", "", 
"", "", "y"), v7 = c("", "", "", "", "u"), v8 = c("", "", "", 
"", "i"), v9 = c("", "", "", "", "o")), .Names = c("v1", "v2", 
"v3", "v4", "v5", "v6", "v7", "v8", "v9"), row.names = c(NA, 
-5L), class = "data.frame")

【讨论】:

  • @fvgs 这里我假设您有一个包含这些字符串的列。
  • 你在哪里假设一个列?读入的数据来自上述格式的 csv。输入和输出都不是单列。我正在尝试您的示例,但输出(使用 View)与所需的数据框非常不同
  • @fvgs 好的,如果它不是单列,那么您必须在其他列中有空格,因为每行中的元素数量不同,我还没有看到您使用 @987654340 @ in read.csv`
  • 我试图通过在最后一个 for 循环中检查 eventName != "" 来解决空白问题。但是使用fill=TRUE 似乎是一个更清洁的解决方案
  • 是的,感谢您的帮助!现在我只需要准确了解每个转换在做什么......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
  • 2014-10-18
  • 2016-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多