14

I have a list containing 98 items. But each item contains 0, 1, 2, 3, 4 or 5 character strings.

I know how to get the length of the list and in fact someone has asked the question before and got voted down for presumably asking such an easy question.

But I want a vector that is 98 elements long with each element being an integer from 0 to 5 telling me how many character strings there are in each list item. I was expecting the following to work but it did not.

lapply(name.of.list,length())

From my question you will see that I do not really know the nomeclature of lists and items. Feel free to straighten me out.

Community
  • 1
  • 1
Farrel
  • 10,244
  • 19
  • 61
  • 99

3 Answers3

10

Farrel, I do not exactly follow as 'item' is not an R type. Maybe you have a list of length 98 where each element is a vector of character string?

In that case, consider this:

R> fl <- list(A=c("un", "deux"), B=c("one"), C=c("eins", "zwei", "drei"))
R> lapply(fl, function(x) length(x))
$A
[1] 2

$B
[1] 1

$C
[1] 3
R> do.call(rbind, lapply(fl, function(x) length(x)))
  [,1]
A    2
B    1
C    3
R> 

So there is you vector of the length of your list, telling you how many strings each list element has. Note the last do.call(rbind, someList) as we got a list back from lapply.

If, on the other hand, you want to count the length of all the strings at each list position, replace the simple length(x) with a new function counting the characters:

R> lapply(fl, function(x) { sapply(x, function(y) nchar(y)) } )
$A
  un deux 
   2    4 

$B
one 
  3 

$C
eins zwei drei 
   4    4    4 

R> 

If that is not want you want, maybe you could mock up some example input data?

Edit:: In response to your comments, what you wanted is probably:

R> do.call(rbind, lapply(fl, length))
  [,1]
A    2
B    1
C    3
R> 

Note that I pass in length, the name of a function, and not length(), the (displayed) body of a function. Because that is easy to mix up, I simply apply almost always wrap an anonymous function around as in my first answer.

And yes, this can also be done with just sapply or even some of the **ply functions:

R> sapply(fl, length)
A B C 
2 1 3 
R> lapply(fl, length)
[1] 2 1 3
R> 
theforestecologist
  • 4,667
  • 5
  • 54
  • 91
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • The first way you did it is what I want. Let me go try that. – Farrel Jan 17 '10 at 03:11
  • Yip, it worked. Fantastic. In fact sapply worked even better because it made a simple single vector which I can now go and cbind onto a preexisting dataframe. Now can you explain to me how lapply(name.of.list,length()) and lapply(name.of.list,function(x) length(x)) are different. – Farrel Jan 17 '10 at 03:19
  • Please see the additional edit at my answer -- in essence `length` is different from `length()` and you want the former. – Dirk Eddelbuettel Jan 17 '10 at 03:48
10

All this seems very complicated - there is a function specifically doing what you were asking for:

lengths  #note the plural "s"

Using Dirks sample data:

fl <- list(A=c("un", "deux"), B=c("one"), C=c("eins", "zwei", "drei"))
lengths(fl)

will return a named integer vector:

A B C 
2 1 3 
Peer Wünsche
  • 175
  • 3
  • 8
0

The code below accepts a list and returns a vector of lengths:

x = c("vectors", "matrices", "arrays", "factors", "dataframes", "formulas", 
      "shingles", "datesandtimes", "connections", "lists")
xl = list(x)
fnx = function(xl){length(unlist(strsplit(x, "")))}
lv = sapply(x, fnx)
doug
  • 69,080
  • 24
  • 165
  • 199