I have a data frame in R that has many rows (over 3000) with F0 (fundamental frequency) tracks of an utterance in it. The rows have the following information in them: speaker ID, group #, repetition #, accent type, sex, and then 50 columns of F0 points. The data looks like this:
Speaker Sex Group Repetition Accent Word 1 2 3 4
105 M 1 1 N AILMENT 102.31030 102.31030 102.31030 102.31127
105 M 1 1 N COLLEGE 111.80641 111.80313 111.68612 111.36020
105 M 1 1 N FATHER 124.06655 124.06655 124.06655 124.06655
But instead of only going to X4, it has 50 points per row, so I have a 3562x56 data frame. I want to change it so each column of data in the F0 track (so after word, from 1:50) gets its own column, with the associated column number as another row. I want to keep all of the information in the first six columns with each data point as well, so it would look like this:
Speaker Sex Group Repetition Accent Word Num F0
105 M 1 1 N AILMENT 1 102.31030
105 M 1 1 N AILMENT 2 102.31030
105 M 1 1 N AILMENT 3 102.31030
105 M 1 1 N AILMENT 4 102.31127
...
105 M 1 1 N COLLEGE 1 111.80641
105 M 1 1 N COLLEGE 1 111.80313
105 M 1 1 N COLLEGE 1 111.68612
105 M 1 1 N COLLEGE 1 111.36020
...
The code I tried to use, while tedious, is as follows:
x = 1
for (i in 1:dim(normrangef0)[1]) {
for (j in 1:50) {
norm.all$Speaker[x] <- normrangef0$Speaker[i]
norm.all$Sex[x] <- normrangef0$Sex[i]
norm.all$Group[x] <- normrangef0$Group[i]
norm.all$Repetition[x] <- normrangef0$Repetition[i]
norm.all$Word[x] <- normrangef0$Word[i]
norm.all$Accent[x] <- normrangef0$Accent[i]
norm.all$Time[x] <- j
norm.all$F0[x] <- normrangef0[i,j+6]
x = x+1
}
}
However, when I do this with norm.all as a NULL object (just defined by norm.all = c() ), I end up with a list of over 200k items, many of which are NAs. When I define norm.all as a data frame (either an empty one or one of all 0s, in the 178100x8 data frame, I get an error:
Error in
$<-.data.frame
(*tmp*
, "Speaker", value = 105L) : replacement has 1 row, data has 0
Is my code just totally off? Is there another way to do this?
Use melt
from "reshape2"
library(reshape2)
melt(mydf, id.vars=c("Speaker", "Sex", "Group", "Repetition", "Accent", "Word"))
# Speaker Sex Group Repetition Accent Word variable value
# 1 105 M 1 1 N AILMENT 1 102.3103
# 2 105 M 1 1 N COLLEGE 1 111.8064
# 3 105 M 1 1 N FATHER 1 124.0666
# 4 105 M 1 1 N AILMENT 2 102.3103
# 5 105 M 1 1 N COLLEGE 2 111.8031
# 6 105 M 1 1 N FATHER 2 124.0666
# 7 105 M 1 1 N AILMENT 3 102.3103
# 8 105 M 1 1 N COLLEGE 3 111.6861
# 9 105 M 1 1 N FATHER 3 124.0666
# 10 105 M 1 1 N AILMENT 4 102.3113
# 11 105 M 1 1 N COLLEGE 4 111.3602
# 12 105 M 1 1 N FATHER 4 124.0666
In base R, you can also use stack
to stack the columns named 1 through 4, and cbind
that with the first group of columns. Alternatively, unlist
will also do this.
You may also want to look into the "data.table" package to get a bit of a speed boost.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With