Lodash _.meanBy() method

Beginner
⏱️ 6 min read
📚 Updated: May 2026
🎯 3 Code examples
🚀 3 Try-it labs
Lodash

What you’ll learn

  • How _.meanBy(array, iteratee) is just baseSum(array, baseIteratee(iteratee, 2)) / array.length.
  • The two iteratee shapes: a function or a _.property path string ('n', 'duration.minutes').
  • The missing-field trap: rows without the property are silently dropped from the sum but still counted in the divisor.
  • Why _.meanBy([], 'n') is NaN (not undefined) and how to guard with Number.isFinite().
  • The same string-concatenation trap inherited from _.mean: one stringy iteratee result wrecks the answer.

Prerequisites

Read _.mean() first—_.meanBy is the same engine with an iteratee layer in front. The skip-rules and string-concat traps documented there all apply.

  • Iteratee shorthand: string → property path, function → itself.
  • baseSum / baseMean: they don’t care if results are numbers—use + blindly and divide.

Overview

The whole function is two lines: baseMean(array, baseIteratee(iteratee, 2)). baseIteratee turns a string or function into a per-element score function; baseMean sums those scores and divides by array.length. Same skip-rules and string traps as _.mean, plus one extra footgun: a row whose iteratee returns undefined is silently excluded from the sum but still increments the divisor.

Path shorthand

Dotted paths work: 'a.b.c'. Same machinery as _.maxBy, _.minBy, _.sumBy.

Missing-field trap

Skipped values lower the sum but not the divisor → partial data pulls the mean toward zero.

Empty → NaN

_.meanBy([], 'n') and _.meanBy(null, 'n') both return NaN—guard with Number.isFinite.

Syntax

javascript
_.meanBy(array, [iteratee = _.identity])
  • array: array to process. Falsy or empty → NaN.
  • iteratee: function or string property path. Default is _.identity—equivalent to _.mean(array). Pass an iteratee whenever you have objects.
  • Returns: number—the arithmetic mean of the projected values.
1

Docs baseline — function vs path shorthand

The official examples: both calls return 5, demonstrating that the function form and the _.property shorthand are interchangeable.

javascript
import meanBy from "lodash/meanBy";

const objects = [{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }];

console.log(meanBy(objects, function (o) { return o.n; })); // 5
console.log(meanBy(objects, "n"));                            // 5

// Nested path
const records = [
  { duration: { minutes: 30 } },
  { duration: { minutes: 45 } },
  { duration: { minutes: 60 } }
];
console.log(meanBy(records, "duration.minutes"));            // 45
Try it Yourself
2

The missing-field trap

Half your rows don’t have the field you’re averaging? Lodash silently drops their values from the sum, but the divisor is still array.length. The result looks like a real average, just… wrong. Filter the array down to rows that have the field if you want a correct answer.

javascript
import meanBy from "lodash/meanBy";

const rows = [
  { n: 1 },
  { x: 2 },   // no 'n' property -> iteratee returns undefined
  { n: 3 }
];

console.log(meanBy(rows, "n"));                                // 1.3333... (4 / 3, NOT 2)

// Correct: filter to rows that have the field, then average
const usable = rows.filter(r => r.n != null);
console.log(meanBy(usable, "n"));                              // 2

// null values DO count (coerced to 0); only undefined is skipped
const withNull = [{ n: 1 }, { n: null }, { n: 3 }];
console.log(meanBy(withNull, "n"));                            // 1.3333... — (1 + 0 + 3) / 3

// String values in the iteratee result still trigger concatenation
const mixed = [{ n: 1 }, { n: "20" }, { n: 3 }];
console.log(meanBy(mixed, "n"));                                // 401  — '120' + 3 = '1203', / 3 = 401
Try it Yourself
3

Empty input, no-iteratee fallback, complex iteratees

Empty / nullish input yields NaN. Omitting the iteratee makes _.meanBy behave like _.mean — great for raw numeric arrays, useless for object arrays. Custom function iteratees let you derive scores on the fly.

javascript
import meanBy from "lodash/meanBy";

console.log(meanBy([], "n"));                  // NaN
console.log(meanBy(null, "n"));                // NaN

// Safe default with Number.isFinite (?? would not catch NaN)
function safeMeanBy(arr, it) {
  const m = meanBy(arr, it);
  return Number.isFinite(m) ? m : 0;
}
console.log(safeMeanBy([], "n"));               // 0

// No iteratee -> _.identity. Works for numbers, NOT for objects.
console.log(meanBy([10, 20, 30]));              // 20  (same as _.mean)
console.log(meanBy([{ n: 1 }, { n: 2 }]));      // NaN — can't average objects

// Complex iteratee: derive a score per row
const orders = [
  { qty: 2, price: 10 },
  { qty: 1, price: 25 },
  { qty: 3, price: 5 }
];
console.log(meanBy(orders, o => o.qty * o.price)); // 20  (20 + 25 + 15 = 60 / 3)
Try it Yourself

📋 _.meanBy vs _.mean vs reduce

InputCodeResultNotes
[10, 20, 30]_.mean(arr)20Use _.mean for raw number arrays.
[{n:1},{n:2},{n:3}]_.meanBy(arr, 'n')2Path shorthand — the common case.
[{a:{b:5}},{a:{b:7}}]_.meanBy(arr, 'a.b')6Dotted path drills in.
[{n:1},{x:2},{n:3}]_.meanBy(arr, 'n')1.33Missing field → partial data lowers the mean.
[{n:1},{n:2}]arr.reduce((a,o)=>a+o.n,0)/arr.length1.5Same result; you write the validation yourself.

Pitfalls to avoid

Missing fields

Silent skip ≠ correct mean

undefined is dropped from the sum but the divisor still counts the row. Filter the array first if “average over rows that have the field” is what you mean.

Empty input

NaN not undefined

NaN ?? 0 is still NaN. Use Number.isFinite() to default.

Stringy values

Concatenation trap inherited from _.mean

If the iteratee returns a string for any row, the running sum becomes a string and the final divide produces nonsense. Cast in the iteratee: o => Number(o.n).

No iteratee on objects

Default iteratee = _.identity

Forgetting the iteratee on an array of objects gives NaN — objects don’t sum. Always pass a path or function for object arrays.

BigInt

Throws

If your iteratee returns BigInt values, you’ll get Cannot mix BigInt and other types. Convert with Number() in the iteratee.

❓ FAQ

_.mean averages the array values directly. _.meanBy(array, iteratee) projects each element through the iteratee first and averages the projections. The iteratee can be a function or a property path string like 'score' or 'a.b.c'.
The iteratee returns undefined for that row. baseSum skips undefined from the running total, but baseMean still divides by array.length—including the skipped row. So _.meanBy([{n:1},{x:2},{n:3}], 'n') is 4/3 ≈ 1.33, not 2. Filter the array first if you want only rows that have the field.
Yes. _.meanBy(records, 'duration.minutes') works because baseIteratee(iteratee, 2) treats string iteratees as property paths via _.property.
It runs, but you get NaN. With no iteratee Lodash falls back to _.identity, which returns the whole object—you can't sum objects. Always pass an iteratee for object arrays.
_.meanBy([], 'n') is NaN, exactly like _.mean([]). baseMean returns 0/0 whenever array.length is 0 or the array is nullish. Guard with Number.isFinite() before using the result.

Summary

  • Purpose: average an array of values via a per-element function or property-path iteratee.
  • Remember: empty/null → NaN; missing fields lower the sum but not the divisor; stringy results concatenate; default iteratee fails on objects.
  • Next: Lodash _.min() or the official Lodash docs for _.meanBy.
Did you know?

_.meanBy(rows, 'n') divides by rows.lengthnot by the count of rows that actually had an n. A missing field drops the value from the sum, not from the divisor, so partial data quietly drags the mean toward zero.

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful