【问题标题】:Importing and analysing non-rectangular .csv files in R在 R 中导入和分析非矩形 .csv 文件
【发布时间】:2015-05-03 17:09:37
【问题描述】:

我正在从 Mathematica 迁移到 R,在那里我不需要在导入期间预测数据结构,特别是在导入之前我不需要预测数据的矩形度。

我有很多文件.csv文件格式如下:

tasty,chicken,cinnamon
not_tasty,butter,pepper,onion,cardamom,cayenne
tasty,olive_oil,pepper
okay,olive_oil,onion,potato,black_pepper
not_tasty,tomato,fenugreek,pepper,onion,potato
tasty,butter,cheese,wheat,ham

行有不同的长度,并且只包含字符串。

在 R 中,我应该如何解决这个问题?

您尝试过什么?

我试过read.table:

dataImport <- read.table("data.csv", header = FALSE)
class(dataImport)
##[1] "data.frame"
dim(dataImport)
##[1] 6   1
dataImport[1]
##[1] tasty,chicken,cinnamon
##6 Levels: ...

我从文档中将其解释为单个列,每个成分列表都作为不同的行。我可以按如下方式提取前三行,每一行都是classfactor,但似乎包含的数据比我预期的要多:

dataImport[c(1,2,3),1]
## my rows
rowOne <- dataImport[c(1),1];
class(rowOne)
## "factor"
rowOne
## [1] tasty,chicken,cinnamon
## 6 Levels: not_tasty,butter,cheese [...]

就我目前所处理的这个问题而言,如果read.table 适合这种数据结构,我将不胜感激。

我的目标是按每行的第一个元素对数据进行分组,并分析每种配方之间的差异。如果它有助于影响数据结构建议,我会在 Mathematica 中执行以下操作:

dataImport=Import["data.csv"];
tasty = Cases[dataImport, {"tasty", ingr__} :> {ingr}]

回答讨论

@G.Grothendieck 提供了使用read.table 和使用reshape2 包进行后续处理的解决方案——这似乎非常有用,我稍后会进行调查。这里的一般建议解决了我的问题,因此接受。

@MrFlick 关于使用tm 包的建议对于以后使用DataframeSource 进行分析很有用

【问题讨论】:

  • 导入后的数据要做什么?大多数 R 的“数据”结构和基本函数最适合矩形数据。你只想要一个字符向量列表吗?您想如何分析差异?
  • @MrFlick 我有兴趣分析每个类别中哪些成分最常见(美味、非美味),这需要进行统计等。我已经稍微简化了我的问题以使问题更小。我在 Mathematica 中使用的实际数据作为一个半有趣的机器学习示例的一部分..
  • 这实际上与mathematica 没有任何关系吧?你能把那个标签删掉吗?
  • 你是对的,已编辑 - 对此感到抱歉。

标签: r import


【解决方案1】:

read.table 试试read.tablefill=TRUE

d1 <- read.table("data.csv", sep = ",", as.is = TRUE, fill = TRUE)

给予:

> d1
         V1        V2        V3     V4           V5      V6
1     tasty   chicken  cinnamon                            
2 not_tasty    butter    pepper  onion     cardamom cayenne
3     tasty olive_oil    pepper                            
4      okay olive_oil     onion potato black_pepper        
5 not_tasty    tomato fenugreek pepper        onion  potato
6     tasty    butter    cheese  wheat          ham   

带有 NA 的 read.table

或者用 NA 值填充空单元格添加 na.strings = ""

d2 <- read.table("data.csv", sep = ",", as.is = TRUE, fill = TRUE, na.strings = "")

给予:

> d2
         V1        V2        V3     V4           V5      V6
1     tasty   chicken  cinnamon   <NA>         <NA>    <NA>
2 not_tasty    butter    pepper  onion     cardamom cayenne
3     tasty olive_oil    pepper   <NA>         <NA>    <NA>
4      okay olive_oil     onion potato black_pepper    <NA>
5 not_tasty    tomato fenugreek pepper        onion  potato
6     tasty    butter    cheese  wheat          ham    <NA>

长格式

如果你想要长格式:

library(reshape2)
long <- na.omit(melt(d2, id.var = c("id", "V1"))[-3])
long <- long[order(long$id), ]

给予:

> long
   id        V1        value
1   1     tasty      chicken
7   1     tasty     cinnamon
2   2 not_tasty       butter
8   2 not_tasty       pepper
14  2 not_tasty        onion
20  2 not_tasty     cardamom
26  2 not_tasty      cayenne
3   3     tasty    olive_oil
9   3     tasty       pepper
4   4      okay    olive_oil
10  4      okay        onion
16  4      okay       potato
22  4      okay black_pepper
5   5 not_tasty       tomato
11  5 not_tasty    fenugreek
17  5 not_tasty       pepper
23  5 not_tasty        onion
29  5 not_tasty       potato
6   6     tasty       butter
12  6     tasty       cheese
18  6     tasty        wheat
24  6     tasty          ham

宽格式 0/1 二进制变量

要将变量部分表示为 0/1 二进制变量,请尝试以下操作:

wide <- cast(id + V1 ~ value, data = long)
wide[-(1:2)] <- 0 + !is.na(wide[-(1:2)])

给出这个:

数据框中的列表

另一种表示形式是数据框中的以下列表,因此 ag$value 是字符向量列表:

ag <- aggregate(value ~., transform(long, value = as.character(value)), c)
ag <- ag[order(ag$id), ]

giving:

> ag
  id        V1                                    value
4  1     tasty                        chicken, cinnamon
1  2 not_tasty butter, pepper, onion, cardamom, cayenne
5  3     tasty                        olive_oil, pepper
3  4      okay   olive_oil, onion, potato, black_pepper
2  5 not_tasty tomato, fenugreek, pepper, onion, potato
6  6     tasty               butter, cheese, wheat, ham

> str(ag)
'data.frame':   6 obs. of  3 variables:
 $ id   : int  1 2 3 4 5 6
 $ V1   : chr  "tasty" "not_tasty" "tasty" "okay" ...
 $ value:List of 6
  ..$ 15: chr  "chicken" "cinnamon"
  ..$ 1 : chr  "butter" "pepper" "onion" "cardamom" ...
  ..$ 17: chr  "olive_oil" "pepper"
  ..$ 11: chr  "olive_oil" "onion" "potato" "black_pepper"
  ..$ 6 : chr  "tomato" "fenugreek" "pepper" "onion" ...
  ..$ 19: chr  "butter" "cheese" "wheat" "ham"

【讨论】:

  • 感谢您,这无疑使我的数据现在可以在data.frame 中使用。我会坚持接受,不要气馁,因为你永远不知道人们会提出什么建议。
  • 已添加长宽表格。
【解决方案2】:

我认为将您的数据放入 data.frame 或 data.table 不会对您有太大帮助,因为这两种形式通常都采用矩形数据。如果你只是想要一个字符向量列表,你可以读入它们。

strsplit(readLines("data.csv"), ",")

这完全取决于您在读入数据后将如何处理数据。如果您打算使用现有函数,他们期望什么输入?

听起来您可能正在跟踪每个食谱中的术语。也许合适的数据结构是来自tm 包的“语料库”,用于文本挖掘。

【讨论】:

  • 我最终使用tm 进行分析,但使用DataframeSource 构建语料库-请问为什么您的建议是不要走这条路?
  • 只是你的数据看起来不像data.frame。它不是矩形的;这些列没有任何意义/意义。将它放在 data.frame 中没有任何好处。您只是添加了一堆 NA 值来填充它。您还可以使用其他来源将数据导入tm,您甚至可以定义自己的数据来源,无论您的数据看起来是什么样的。仅仅因为它是“数据”并不意味着它必须进入 data.frame。
  • 了解并非所有数据都是针对data.frame的,只是对R数据结构不熟悉。在 Mathematica 中,我将每一行作为 List 导入,然后将它们重新排列成 Association,本质上是字典 'data={"foo","bar"},"okay"->{"goo" ,"car"}|>;data["tasty"]' 这将为我提供所有带有美味钥匙的东西。感谢回复
  • 这基本上就是我的建议。它会生成一个向量列表(尽管在这种情况下是一个未命名的列表,因为我不清楚你的名字/键来自哪里)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 2017-05-14
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 2017-01-31
相关资源
最近更新 更多