Lars Lars - 3 years ago 190
R Question

What is wrong with my for-loop? -gsub rownames

I want to iterate over all my rows and rename them. Basically I just want to remove some of the words(same pattern in every row name) in my dataframe.

code:

for (i in rownames(df)) {

row.names(df)[i] <- gsub("*The words I want to remove*", "", row.names(df)[i])
}


I get the following error:


Error in
row.names<-.data.frame
(
*tmp*
, value = c("The words I want to remove", :
invalid 'row.names' length


Note that the code works fine outside of a loop.

Answer Source

Your sequence is not good :

Here, i in rownames(df) is successively each of your rown names :

for (i in rownames(mtcars)) {
+   print(i)
+ }
[1] "Mazda RX4"
[1] "Mazda RX4 Wag"
[1] "Datsun 710"
...

So row.names(df)[i] is trying to do row.names(df)["yourrowname"] i.e : row.names(mtcars)["Mazda RX4"] which return NA.

The way you wrote your code, i has to be a number. So :

for (i in seq_along(rownames(df))) {
  print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
... 

Now, for replacing row names, you need to double bracket the i. Here's an example with mtcars :

data("mtcars")
rownames(mtcars)
[1] "Mazda RX4"           "Mazda RX4 Wag"      
[3] "Datsun 710"          "Hornet 4 Drive"     
[5] "Hornet Sportabout"   "Valiant"            
[7] "Duster 360"          "Merc 240D"          
[9] "Merc 230"            "Merc 280"           
[11] "Merc 280C"           "Merc 450SE"         
[13] "Merc 450SL"          "Merc 450SLC"        
[15] "Cadillac Fleetwood"  "Lincoln Continental"

for (i in seq_along(rownames(mtcars))) {

  row.names(mtcars)[[i]] <- gsub(" ", "_", row.names(mtcars)[[i]])
}
rownames(mtcars)

[1] "Mazda_RX4"           "Mazda_RX4_Wag"      
[3] "Datsun_710"          "Hornet_4_Drive"     
[5] "Hornet_Sportabout"   "Valiant"            
[7] "Duster_360"          "Merc_240D"          
[9] "Merc_230"            "Merc_280"           
[11] "Merc_280C"           "Merc_450SE"         
[13] "Merc_450SL"          "Merc_450SLC" 

But as stated in the comments, you don't need a for loop here :

rownames(mtcars) <- gsub(" ", "_", row.names(mtcars))
rownames(mtcars)
[1] "Mazda_RX4"           "Mazda_RX4_Wag"      
[3] "Datsun_710"          "Hornet_4_Drive"     
[5] "Hornet_Sportabout"   "Valiant"            
[7] "Duster_360"          "Merc_240D"          
[9] "Merc_230"            "Merc_280"           
[11] "Merc_280C"           "Merc_450SE"         
[13] "Merc_450SL"          "Merc_450SLC"  
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download