在 R 中导入和分析非矩形 .csv 文件

Importing and analysing non-rectangular .csv files in R

我正在从 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: ...

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

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

进行分析很有用

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   

read.table 与 NA

或用 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 或 data.table 中不会对您有多大帮助,因为这两种形式通常都采用矩形数据。如果你只想要一个字符向量列表,你可以读入它们。

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

这完全取决于您读入数据后要对数据做什么。如果您打算使用现有功能,他们期望什么输入?

听起来您可能正在跟踪每个食谱中的术语。也许合适的数据结构是 tm 文本挖掘包中的 "corpus"。