1
$\begingroup$

I'd like to fit a model where one of the inputs is a variable length list.

For example

FindFit[{{1, {0, 1}, 3}, {2, {1, 1}, 6}, {3, {1, 0, 1}, 8}}, c1*x + c2*Plus @@ y, {c1, c2}, {x, y}]

Returns the error FindFit: First argument [...] in FindFit is not a list or a rectangular array. I guess another function should be used instead of FindFit.

What's the best way to do it?

$\endgroup$
5
  • 1
    $\begingroup$ your data is not in any of the forms allowed. See first 2 lines in help. $\endgroup$
    – Nasser
    May 23 '20 at 12:29
  • $\begingroup$ @Nasser What function should be used instead for such a function with variable length lists as a variable? $\endgroup$
    – Robe
    May 23 '20 at 12:36
  • 1
    $\begingroup$ I am not really sure. As I do not understand what your data represents in this context of fitting. But as you can see, Mathematica's FindFit does not accept this structure of your data. May be someone else knows more and can help. $\endgroup$
    – Nasser
    May 23 '20 at 12:38
  • $\begingroup$ @Nasser I want to find certain coefficients (fitting), in the example c1 and c2, which are in a function (in the example c1*x+c2*Plus@@y) whose inputs can be lists of variable length. The data is just an example $\endgroup$
    – Robe
    May 23 '20 at 13:20
  • 4
    $\begingroup$ Do the processing Plus @@ y on the data, not in the model. $\endgroup$ May 23 '20 at 13:21
1
$\begingroup$

Do the summation on your data before modeling, then fit to a simpler model:

FindFit[
  {#1, Plus @@ #2, #3}& @@@ {{1, {0, 1}, 3}, {2, {1, 1}, 6}, {3, {1, 0, 1}, 8}},
  c1 x + c2  y,
  {c1, c2},
  {x, y}
]

{* Out: {c1 -> 2., c2 -> 1.} *)

In passing, I would also recommend that you upgrade to LinearModelFit or NonlinearModelFit for your data fitting needs: you will get access to a lot of interesting statistical descriptors together with the results of the fit.

$\endgroup$
0
$\begingroup$

Not sure whether I got your point, Assuming the second part of your list is of varying length and the values are positive integers you can do a kind of Gödelisation. To encode the list:

codeIt[list_] := Module[{len = Length@list, primes},
  primes = Prime[Range@len];
  Times @@ (primes^list)
  ]

so the list {1, 0, 3} is encoded to 250. To decode use:

decodeIt[input_Integer] := Module[{temp = FactorInteger[input],
   largestPrime, (* largest prime in list *)
   outPrimes, (* 
   list of primes up to largestPrime*)
   res 
   },
  largestPrime = First[Last[temp]];
  outPrimes = Prime[Range@PrimePi[largestPrime]];
  res = Join[Join[{#}, {0}] & /@ Complement[outPrimes, First /@ temp],
     temp];
  Last /@ SortBy[res, First]
  ]

(this could be written in fewer lines but less readable). So test

    decodeIt[250]
(*{1, 0, 3}*)

Then we have your input:

list = {{1, {0, 1}, 3}, {2, {1, 1}, 6}, {3, {1, 0, 1}, 8}}

encode it:

inputFit = MapAt[codeIt, list, {All, 2}]

Do the fitting-job

    FindFit[inputFit, c1 *x + c2*y, {c1, c2}, {x, y}]
(*{c1 -> 6., c2 -> -1.}*)

then you can use the fitted function and decode the output to get lists again (Gödel must have been a tough guy).

$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.