Как читать несколько строк файла в одну строку блока данных

У меня есть файл данных, где отдельные образцы разделены пустой строкой, и каждое поле находится в собственной строке:

age 20
weight 185
height 72

age 87
weight 109
height 60

age 15
weight 109
height 58

...

Как я могу прочитать этот файл в dataframe, чтобы каждая строка представляла образец с столбцами возраста, веса, высоты?

    age    weight    height

1   20      185        72  
2   87      109        60
3   15      109        58
...
3
Исправлен вопрос, теперь должен быть ясен из примера.
добавлено автор turtle, источник
grrrr ... это не место для "это"
добавлено автор Carl Witthoft, источник
age , weight и т. д.) являются значениями или они похожи: возраст 20 и в следующей строке weight 185 ...?
добавлено автор Arun, источник

6 ответы

@ user1317221_G показал подход, который я бы взял, но прибегал к загрузке дополнительного пакета и явным образом генерировал группы. Группы (переменная идентификатора) являются ключом к получению любого типа ответа reseape для работы. Матричные ответы не имеют такого ограничения.

Вот приблизительный подход в базе R:

mydf <- read.table(header = FALSE, stringsAsFactors=FALSE, 
                   text = "age 20
                   weight 185
                   height 72

                   age 87
                   weight 109
                   height 60

                   age 15
                   weight 109
                   height 58
                   ")

# Create your id variable
mydf <- within(mydf, {
  id <- ave(V1, V1, FUN = seq_along)
})

С переменной id ваша трансформация проста:

reshape(mydf, direction = "wide", 
        idvar = "id", timevar="V1")
#   id V2.age V2.weight V2.height
# 1  1     20       185        72
# 4  2     87       109        60
# 7  3     15       109        58

Или:

# Your ids become the "rownames" with this approach
as.data.frame.matrix(xtabs(V2 ~ id + V1, mydf))
#   age height weight
# 1  20     72    185
# 2  87     60    109
# 3  15     58    109
3
добавлено
+1 ave - хороший выбор, и мне нравится решение xtabs , о котором я всегда забываю.
добавлено автор user1317221_G, источник

Чтобы расширить ответ на @ BlueMagister, вы можете использовать сканирование с некоторыми параметрами, чтобы прочитать это непосредственно в списке, а затем преобразовать список в кадр данных:

tmp <- scan(text = "
age     20
weight  185
height  72

age     87
weight  109
height  60

age     15
weight  109
height  58", multi.line=TRUE, 
  what=list('',0,'',0,'',0), 
  blank.lines.skip=TRUE)

mydf <- as.data.frame( tmp[ c(FALSE,TRUE) ] )
names(mydf) <- sapply( tmp[ c(TRUE,FALSE) ], '[', 1 )

Это предполагает, что переменные в записи всегда находятся в одном порядке.

2
добавлено

Вот что я пробовал с помощью scan :

##substitute text with file depending on your input
##read in three strings separated by spaces, multi-line input
y <- scan(text=x,what=list(character(),character(),character())
  ,sep="\n",multi.line=TRUE)
##combine into a matrix of strings
y <- do.call(cbind,y)
#     [,1]     [,2]         [,3]       
#[1,] "age 20" "weight 185" "height 72"
#[2,] "age 87" "weight 109" "height 60"
#[3,] "age 15" "weight 109" "height 58"
##set column names based on text from the first row
colnames(y) <- regmatches(y[1,],regexpr("^\\w+",y[1,]))
##remove non-numeric characters
y <- gsub("\\D+","",y)
##convert to number format, preserving matrix structure
y <- apply(y,2,as.numeric)
##convert to data frame (if necessary)
y <- data.frame(y)
1
добавлено
df <- read.table(text ="
age     1
weight  1
height  6

age     2
weight  7
height  2

age     4
weight  8
height  9", header=FALSE) 

df$ID <- rep(1:3, each=3)
library(reshape2)
newdf <- dcast(df, ID~V1, value.var="V2")

#     ID age height weight
#1  1   1      6      1
#2  2   2      2      7
#3  3   4      9      8
1
добавлено
+1. Это тот подход, который пришел мне на ум. Мне не нравится «жестко кодировать» переменную идентификатора так, как вы это делали.
добавлено автор A5C1D2H2I1M1N2O1R2T1, источник
Это больше походит на это! Хорошая альтернатива.
добавлено автор A5C1D2H2I1M1N2O1R2T1, источник
@AnandaMahto. Ваше право, хотя я мог бы сделать еще один шаг к автоматизации с помощью: df $ ID <- rep (1: (length (df [ 1])/3), each = 3)
добавлено автор user1317221_G, источник

Если в исходном файле эти три переменные полностью опущены, один простой способ - просто прочитать файл в виде двух столбцов (имена сначала, числа в секунду), а затем перевести второй столбец в матрицу. Если я сниму df с ответа пользователя1317221_G,

matrix(df$V2,ncol=3,byrow=TRUE)
     [,1] [,2] [,3]
[1,]    1    1    6
[2,]    2    7    2
[3,]    4    8    9

Добавление имен строк и/или столбцов тривиально. Извините за получение порядка столбцов «возраст, вес, высота» :-)

0
добавлено

Другое решение

data <- readLines('c:\\relatorios\\bla.txt') # Read the data
data <- data[data != ''] # Remove the white lines
names <- unique(gsub('[0-9]*','',data)) # Get the names
data <- matrix(as.real(gsub('[^0-9]*','',data)),ncol=3,byrow=T) # Create matrix
colnames(data) <- names # Set the names
0
добавлено