I am new to the beautiful language of R and currently I am having difficulties understanding the following:
I am loading in a CSV file. This CSV file contains two columns. The first column is a unique ID. The second column is named 'content'. The content column is basically all the readable text from a specific URL.
If I print the content of the first row of the second column I get the following output.
Text[1:1,2:2]
[1] Autoservice Hofra Home \xa0 Home Contact \xa0 Autoservice Hofra \xa0 Home Contact Autoservice Hofra Welkom op onze website \xa0 \xa0LASSA BANDEN DEALER \xa0 Wanneer is mijn auto toe aan een onderhouds inspectie Iedere auto heeft een instructieboekje Dat ligt meestal in het dashboardkastje van uw auto In dat boekje staat hoe en wanneer u de auto onderhoudt Autoservice Hofra Albert Einsteinweg 12 6045 GX Roermond Tel 0654965305 Kleine en grote beurt Bij Autoservice Hofra kun je terecht voor een grote en kleine beurt voor de zomer en winter checks maar ook airco onderhoud Zo zorgen we dat je niet alleen veilig en comfortabel de weg op gaat maar ook nog eens extra lang plezier hebt van je auto \xa0 We vervangen motorolie en het oliefilter vullen de ruitenvloeistof koelvloeistof en remvloeistof bij en houden rekening met de milieutoeslag Een groot deel van de checks die bij een APK worden gedaan komen ook bij de grote beurt aan bod Het is daarom voordelig om deze te combineren De motormanagement van de auto wordt zorgvuldig uitgelezen met diagnose apparatuur waardoor storingen en andere meldingen aan het licht komen \xa0 \xa0 \xa0 Airco Check \xa0Houdt de airco uw auto op de juiste temperatuur Ontwasemt de airco de autoruit slecht En blaast hij nog frisse lucht Doe de Airco Check Ook als het geen zomer is Wij voeren alle voorkomende onderhoudswerkzaamheden uit aan uw auto voor een zeer scherpe prijs Bij een duurdere reparatie wordt er te allen tijde overleg gepleegd met u Daarnaast zijn we in het bezit van de juiste kennis en gereedschappen om alle voorkomende reparaties uit te voeren \xa0\xa0Laat de werkzaamheden uitvoeren wanneer u dat uitkomt Home \xa0 \xa0 Contact
5432 Levels: ...
If I print the type of this first row of the second column, I get the type integer
typeof(Text[1:1,2:2])
[1] "integer"
Could someone explain me why specific column is having a type 'integer' while it is containing characters. I am also confused about the '5432 levels: ...' part. What is meant with 'levels' in R?
Finally, what I want to do is convert each row of the 'content' column into characters so I can apply for example remove all rows which have a length of < 200, my code:
SText <- subset(Text, nchar(as.character(content)) > 200)
Right now I get the error:
Error in type(Text[1:1, 2:2]) : could not find function "type"
How can I solve this problem? Any help and information would be highly appreciated!
In the background, and for efficiency reasons, factors are stored as numbers. And by default, read.csv() reads characters columns as factors (which makes sense in a statistical world), hence the fact that it is an integer. You should use stringsAsFactors = FALSE on read.csv() to get a character vector (not a factor).
The 5432 levels: ... refers to the levels of the factor contained in this column. A factor always keeps track of ALL its original possible levels. So even if you just extract one element, it will still have all the information about the level.
typeof() is not the function you should use if you need to know the content of an object. As stated in the doc, typeof() returns the internal representation of the object. Hence the integer you get.
You should try class() instead.
read your csv by specifying stringsAsFactors=FALSE
DF <- read.csv("/Users/mypath/finalTotal.csv", stringsAsFactors=FALSE)
DF2 <- read.csv("/Users/mypath/model.csv", stringsAsFactors=FALSE)
\xa0 is a non-breaking space in Latin1 (ISO 8859-1) in your DFText. You should replace it with a space.
DFText[,2] = gsub("\xa0", " ", DFText[,2])
I'm importing data from notepad++ to R (I made a mistake by not saving my data as dataframe, so I need to manually fix missing values in a text editor).
All goes well, until R reaches a certain line (1499). After I fix this one, R suddenly detects mistakes in lines before (1434) that were no problem before. I can't seem to find any problems with the line also (where the other lines clearly contained missing values. Does anyone know what is wrong?
My code: cdaalles <- read.table("cda4.txt", header = TRUE, comment.char = "", sep = ",")
From there, R is returning me the rows that have missing values, after which I fix them:
e.g. Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings, :
line 21 did not have 17 elements
20,"RT #Matthijs85: Ligt het trouwens aan mij
of wordt verschil CDA/VVD nu heel groot uitgelicht, terwijl ze feitelijk 92% hetzelfde stemmen?
#…",FALSE,0,NA,2015-03-17 23:50:11,FALSE,NA,"577980277907189760",NA,"Twitter Web Client","tweetziek",3,TRUE,FALSE,NA,NA
21,"RT #RenskeLeijten: Zeer gebalanceerd commentaar bij nieuwsuur door coryfeeën van VVD en PvdA. Maken verrassend gehakt van CDA " ,missing, missing, missing, missing, missing,missing,missing, missing ,missing, missing, missing, missing, missing,missing,missing
After that, R reads the line and jumps to the next problem it encounters.
But then R returns a mistake for this line (after it has already read it, as I fixed line 1499 before this error message):
1434,"Rutte: stem op CDA is verloren stem.vvd en cda die de middenklasse vertegenwoordigen en keihard afgebroken wordt door de vvD.",FALSE,0,NA,2015-03-17 21:10:12,FALSE,NA,"577940017995227136",NA,"Twitter Web Client","duckie1098",0,FALSE,FALSE,NA,NA
For completeness line 1499 before and after fixing:
Before:
1499,"RT #klaassenmarja: Rutte is een huichelaar, maar het CDA heeft ook steun
After:
1499,"RT #klaassenmarja: Rutte is een huichelaar, maar het CDA heeft ook steun",missing,missing,missing, missing,missing,missing, missing,missing,missing, missing,missing,missing, missing,missing,missing
If anyone knows what's wrong, please help me! It's for my thesis, so its pretty important to me! I tried to delete line 1434 to fix the problem, but it keeps returning the error message even after I delete it. So i don't know how to fix it!
Sample of correctly read data by R (copied from notepad++)
,"text","favorited","favoriteCount","replyToSN","created","truncated","replyToSID","id","replyToUID","statusSource","screenName","retweetCount","isRetweet","retweeted","longitude","latitude"
1,"RT #cdavandaag: De hashtag #ikstemCDA is deze maand al 7.500 (!) keer gebruikt, fantastisch. Op naar een mooi uitslag. #CDA #PS15 http://t.…",FALSE,0,NA,2015-03-17 23:58:23,FALSE,NA,"577982342775615488",NA,"Twitter for iPhone","Cecile2511",25,TRUE,FALSE,NA,NA
2,"RT #Matthijs85: Ligt het trouwens aan mij
of wordt verschil CDA/VVD nu heel groot uitgelicht, terwijl ze feitelijk 92% hetzelfde stemmen?
#…",FALSE,0,NA,2015-03-17 23:58:04,FALSE,NA,"577982262282698752",NA,"Twitter Web Client","meneerharmsen",3,TRUE,FALSE,NA,NA
3,"#PuckPetrus bang makerij bemoei je niet met je buurman les 1
wil jij de les gelezen worden ?
#vvd #pvda #d66 #cda",FALSE,0,"PuckPetrus",2015-03-17 23:57:39,FALSE,"577980323885105152","577982156426899458","1378104055","Twitter Web Client","pufpufpafpaf",0,FALSE,FALSE,NA,NA
4,"RT #FrankScholman: Het #CDA kiest #LagereLasten! Hier hebben we 7 goede redenen voor: http://t.co/utQt0LfEzl. #NOSdebat #PS15 #MeerBanen ht…",FALSE,0,NA,2015-03-17 23:57:36,FALSE,NA,"577982146582806528",NA,"Twitter for iPhone","gijsdupont",4,TRUE,FALSE,NA,NA
5,"RT #Jan_Slagter: In Hilversum werden de Buma awards uitgereikt, en Buma wint het #nosdebat #cda",FALSE,0,NA,2015-03-17 23:56:36,FALSE,NA,"577981895570546688",NA,"Twitter for iPhone","Ztrmarco",38,TRUE,FALSE,NA,NA
6,"RT #StSteenbakkers: Peiling Maurice de Hond: tweestrijd VVD en CDA! Stem CDA!!! #Lagerelasten #CDA #100pBrabant",FALSE,0,NA,2015-03-17 23:56:31,FALSE,NA,"577981871168090113",NA,"Twitter for iPhone","gijsdupont",5,TRUE,FALSE,NA,NA
7,"#PuckPetrus dat ze ze blijven doen 30 jaar lang
https://t.co/MncIMSNtoO
#vvd #pvda #d66 #cda",FALSE,0,"PuckPetrus",2015-03-17 23:56:15,FALSE,"577980323885105152","577981803627171840","1378104055","Twitter Web Client","pufpufpafpaf",0,FALSE,FALSE,NA,NA
8,"RT #cdavandaag: .#SybrandBuma pleit tijdens #NOSdebat voor #maatschappelijkedienstplicht. Waarom? Lees meer: http://t.co/5HkCxRrOO8. http:/…",FALSE,0,NA,2015-03-17 23:55:40,FALSE,NA,"577981660261666816",NA,"Twitter for iPhone","Cecile2511",48,TRUE,FALSE,NA,NA
9,"RT #Pran_Westerdam: Stem niet op de PVDA, VVD, D66, GL en CDA: niets doen wordt onze totale ondergang, dat erkennen zal als eerste moeten g…",FALSE,0,NA,2015-03-17 23:55:36,FALSE,NA,"577981641475387392",NA,"Twitter Web Client","worrienie",2,TRUE,FALSE,NA,NA
10,"RT #NederlandKiest: Buma (CDA): Rutte moet kijken naar de Nederlander. De toekomst van onze kinderen is er een met leenstelsel en hoogste s…",FALSE,0,NA,2015-03-17 23:54:22,FALSE,NA,"577981332703309824",NA,"Twitter for iPhone","Cecile2511",34,TRUE,FALSE,NA,NA
Following up on a question I only posted minutes ago, I need to ask another question. The previous question failed to note that I also have to look through the contents of each individual file. In other words, I have to loop through all files in a directory, and through each line of each file.
Every file name looks like this.
airbag.WS-U-E-A.lst
. is a seperator, .lst is the extension (readable as text).
Each file contains data per line, such as
/home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000075.data.ids.xml: <sentence>ja voor den airbag op te pompen eh :p</sentence>
/home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000129.data.ids.xml: <sentence>Dobby , als ze valt heeft ze dan wel al ne airbag hee</sentence>
What I want to do is, in R create a new dataset that contains data from all files. Ideally it would look like this:
ID | filename | word | component | left-context | right-context
----------------------------------------------------------------------------------------------------------------
1 airbag.WS-U-E-A.lst airbag WS-U-E-A ja voor den op te pompen eh :p
2 airbag.WS-U-E-A.lst airbag WS-U-E-A Dobby , als ze valt heeft ze dan wel al ne hee
ID is simply the row's id, can be done like so:
row.names <- "id"
filename is the name of the file (obviously), which I can do like so:
files <- list.files(pattern="*.lst", full.names=T, recursive=FALSE)
d <- data.frame(fileName = unname(sapply(files, basename)))
I can then strip the word and component from the filename
d$word <- gsub("\\..+", "", d$fileName, perl=TRUE)
d$component <- gsub("^[^.]+.", "", d$fileName, perl=TRUE)
d$component <- gsub(".lst$", "", d$component, perl=TRUE)
Now comes the hard part that I haven't figured out yet...
All the commands I have written down above can be done by only looping the files and get their filename. However, as I said each file contains multiple sentences that I need to dissect and put on different rows. See example above. You'll see that the filename, the word and the component are identical - yet the left and right context aren't. That's because they are two different sentences, in the same file.
Maybe an example with two files makes my question clearer.
adapter.WR-P-P-F.lst
/home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000026.data.ids.xml: <sentence>Een aanpassingseenheid ( adapter ) , aangebracht in een behuizing voornamelijk bestaande uit in- en uitvoereenheden , een koppeleenheid , een geheugeneenheid , een besturingseenheid ( met actieve en passieve elementen en monolitische geïntegreerde schakelingen ) en een elektrische voedingseenheid . ></sentence>
/home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000026.data.ids.xml: <sentence>ID="1">Het toestel ( adapter ) draagt zorg voor de overbrenging van gegevens , met een snelheid van 10 Mbps ( megabits per seconde ) , tussen meerdere automatische gegevensverwerkende machines in een digitaal netwerk . " ></sentence>
/home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000034.data.ids.xml: <sentence>Overwegende dat deze sensoren niet zijn ontworpen op de installatie van een gepantserde kabel ; dat de mogelijkheid moet worden geboden dat de gepantserde kabel niet verplicht wordt gesteld voor de aansluiting tussen de sensor en de adapter , maar alleen van de adapter naar het controleapparaat ; dat het bijgevolg noodzakelijk is de verordening dienovereenkomstig te wijzigen ;</sentence>
airbag.WS-U-E-A.lst
/home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000075.data.ids.xml: <sentence>ja voor den airbag op te pompen eh :p</sentence>
/home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000129.data.ids.xml: <sentence>Dobby , als ze valt heeft ze dan wel al ne airbag hee</sentence>
If those were the only two files in my directory, my R commands would do the following things:
Look through each individually file
Put each sentence (i.e. every line) in a new row
Based on in which file that sentence is, fill in the filename, word and the component
With regular expressions, get the left and right context from the sentence
Assign IDs per row
The output would then look like this
ID | filename | word | component | left-context | right-context
----------------------------------------------------------------------------------------------------------------
1 adapter.WR-P-P-F.lst adapter WR-P-P-F Een aanpassingseenheid ( ) , aangebracht in een behuizing voornamelijk bestaande uit in- en uitvoere[...]
2 adapter.WR-P-P-F.lst adapter WR-P-P-F ID="1">Het toestel ( ) draagt zorg voor de overbrenging van gegevens [...]
3 adapter.WR-P-P-F.lst adapter WR-P-P-F [...] tussen de sensor en de naar het controleapparaat ; [...]
4 airbag.WS-U-E-A.lst airbag WS-U-E-A ja voor den op te pompen eh :p
5 airbag.WS-U-E-A.lst airbag WS-U-E-A Dobby , als ze valt heeft ze dan wel al ne hee
(I left out some content for brevity's sake, denoted by [...])
I understand that this seems like quite a large question, however basically what I need is a way to loop the files themselves, and extract line per line into a new row whilst putting information about the file itself in separate columns (on the same row). Extracting the text from the lines is something I should be able to do by myself. For example, it would bring me a long way if I could just get something such as this:
ID | filename | word | component | sentence
----------------------------------------------------------------------------------------------------------------
1 adapter.WR-P-P-F.lst adapter WR-P-P-F /home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000026.data.ids.xml: <sentence>Een aanpassingseenheid ( adapter ) , aangebracht in een behuizing voornamelijk bestaande uit in- en uitvoereenheden , een koppeleenheid , een geheugeneenheid , een besturingseenheid ( met actieve en passieve elementen en monolitische geïntegreerde schakelingen ) en een elektrische voedingseenheid . ></sentence>
2 adapter.WR-P-P-F.lst adapter WR-P-P-F /home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000026.data.ids.xml: <sentence>ID="1">Het toestel ( adapter ) draagt zorg voor de overbrenging van gegevens , met een snelheid van 10 Mbps ( megabits per seconde ) , tussen meerdere automatische gegevensverwerkende machines in een digitaal netwerk . " ></sentence>
3 adapter.WR-P-P-F.lst adapter WR-P-P-F /home/nobackup/SONAR/COMPACT/WR-P-P-F/WR-P-P-F0000034.data.ids.xml: <sentence>Overwegende dat deze sensoren niet zijn ontworpen op de installatie van een gepantserde kabel ; dat de mogelijkheid moet worden geboden dat de gepantserde kabel niet verplicht wordt gesteld voor de aansluiting tussen de sensor en de adapter , maar alleen van de adapter naar het controleapparaat ; dat het bijgevolg noodzakelijk is de verordening dienovereenkomstig te wijzigen ;</sentence>
4 airbag.WS-U-E-A.lst airbag WS-U-E-A /home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000075.data.ids.xml: <sentence>ja voor den airbag op te pompen eh :p</sentence>
5 airbag.WS-U-E-A.lst airbag WS-U-E-A /home/nobackup/SONAR/COMPACT/WR-U-E-A/WR-U-E-A0000129.data.ids.xml: <sentence>Dobby , als ze valt heeft ze dan wel al ne airbag hee</sentence>
I hope it's clear what I am trying to say. If not feel free to ask.
Create two data.frames and merge them
# what you have so far (file-level data.frame)
files <- list.files(pattern="*.lst", full.names=T, recursive=FALSE)
d <- data.frame(fileName = unname(sapply(files, basename)))
d$word <- gsub("\\..+", "", d$fileName, perl=TRUE)
d$component <- gsub("^[^.]+.", "", d$fileName, perl=TRUE)
d$component <- gsub(".lst$", "", d$component, perl=TRUE)
# new data.frame containing contents of files
e <- do.call(rbind, lapply(files, function(x) {
# create two-column data.frame for each file
## first column is fileName
## second column is data from each file
data.frame(fileName = x, sentence = readLines(x), stringsAsFactors = FALSE)
}))
# the above returns a data.frame `e` containing all file records
# pull out the sentence (probably better ways to do this)
e$sentence <- sapply(strsplit(e$sentence, ".xml: ", fixed = TRUE), `[`, 2)
e$sentence <- gsub("<sentence>", "", e$sentence, fixed = TRUE)
e$sentence <- gsub("</sentence>", "", e$sentence, fixed = TRUE)
# merge `d` and `e` by the common column name `fileName`
out <- merge(d, e, by = "fileName", all = TRUE)
# extract your two "context" variables by splitting the sentence variable by `word`
contexts <- strsplit(out$sentence, out$word)
## this is the left-context (everything to the left of the word)
out$`left-context` <- sapply(contexts, `[`, 1)
## this is the right-context (everything to the right of the word)
out$`right-context` <- sapply(contexts, `[`, 2)
#set the working directory as shown in (setwd function) and manually move all your files into one directory, so the analysis is nice and clean. You have to decide where you keep all files in a directory. Below, I showed you that I kept all my files in "test" directory.
setwd("C:/Users/username/Desktop/test") #windows
setwd("/home/username/Desktop/test") #linux
files <- list.files()
df2 <- data.frame(matrix(nrow = 1, ncol = 5), stringsAsFactors = FALSE)
colnames(df2) <- c("filename", "word", "component", "left_context", "right_context")
for(i in files){
word = sub("([a-z]+)(.)([A-Z-]+)(.*)", "\\1", i)
component = sub("([a-z]+)(.)([A-Z-]+)(.*)", "\\3", i)
list1 <- scan(i, sep = ">", what = list("character", "character"))
context = unlist(lapply(list1[[2]], function(x) gsub('</sentence', '', x) ))
for(j in 1:length(context)){
left_context = strsplit(context[j], word)[[1]][1]
right_context = strsplit(context[j], word)[[1]][2]
df1 <- data.frame(filename = i,
word = word,
component = component,
left_context = left_context,
right_context = right_context,
stringsAsFactors = FALSE)
df2 <- rbind(df2, df1)
}
}
df2 <- df2[2:nrow(df2),]
df2 <- cbind(data.frame(ID = 1:nrow(df2), stringsAsFactors = FALSE), df2)
View(df2)
output:
print(df2)
ID filename word component left_context right_context
1 adapter.WR-P-P-F.lst.txt adapter WR-P-P-F Een aanpassingseenheid ( ) , aangebracht in een behuizing voornamelijk bestaande uit in- en uitvoereenheden , een koppeleenheid , een geheugeneenheid , een besturingseenheid ( met actieve en passieve elementen en monolitische geïntegreerde schakelingen ) en een elektrische voedingseenheid . >
2 adapter.WR-P-P-F.lst.txt adapter WR-P-P-F ID="1">Het toestel ( ) draagt zorg voor de overbrenging van gegevens , met een snelheid van 10 Mbps ( megabits per seconde ) , tussen meerdere automatische gegevensverwerkende machines in een digitaal netwerk . " >
3 adapter.WR-P-P-F.lst.txt adapter WR-P-P-F Overwegende dat deze sensoren niet zijn ontworpen op de installatie van een gepantserde kabel ; dat de mogelijkheid moet worden geboden dat de gepantserde kabel niet verplicht wordt gesteld voor de aansluiting tussen de sensor en de , maar alleen van de
4 airbag.WS-U-E-A.lst.txt airbag WS-U-E-A ja voor den op te pompen eh :p
5 airbag.WS-U-E-A.lst.txt airbag WS-U-E-A Dobby , als ze valt heeft ze dan wel al ne hee
You can extract the data from the files using readLines. In your case, you can use nested loops to build up your data -- one to loop over the files, and within that, a loop on each line.
As an example, I've set up some files in my ~/test directory:
$ ls ~/test
file1.txt file2.txt
The files look like so:
$ ls | xargs cat
I am line 1 from file1.
I am line 2 from file1.
I am line 1 from file2.
I am line 2 from file2.
Now I can loop through them and grab the file name and the contents -- I'm not doing any regexes or processing of this information, as you have indicated you can do so on your own. This is solely to illustrate how you might use two loops to add the information from the file name and the file contents into the same row:
dir <- '~/test'
df <- data.frame(filename=c(), row.index=c(), row.contents=c())
for (file in list.files(dir)) {
filename = paste0(dir, '/', file)
i <- 1
for (line in readLines(filename)) {
df <- rbind(df, data.frame(filename=filename, row.index=i, row.contents=line))
i <- i + 1
}
}
This results in the following data.frame:
> df
filename row.index row.contents
1 ~/test/file1.txt 1 I am line 1 from file1.
2 ~/test/file1.txt 2 I am line 2 from file1.
3 ~/test/file2.txt 1 I am line 1 from file2.
4 ~/test/file2.txt 2 I am line 2 from file2.
Using rbind like this is probably not the most efficient way to do this. Another way that's probably more efficient would be to build up a vector for each column in your final dataframe and then create the dataframe from those vectors once you're done. That would avoid the potentially costly rbind() operation.