Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type Narrowing an object which is either dfd.Series or dfd.DataFrame to dfd.DataFrame #640

Open
bml1g12 opened this issue Apr 18, 2024 · 1 comment

Comments

@bml1g12
Copy link

bml1g12 commented Apr 18, 2024

Is your feature request related to a problem? Please describe.

I am unclear on the recommended way of type narrowing a dfd.Series ❘ dfd.DataFrame object to a dfd.DataFrame

Describe the solution you'd like

e.g. this should work, or some other approach that achieves the type narrowing

  if (!(multiMetricDf instanceof dfd.DataFrame)) {
    throw new Error(
      `Expected a DataFrame here but got ${multiMetricDf.constructor.name}`,
    )
  }

The above code snippet does not work as it can log " "Expected a DataFrame here but got DataFrame"" i.e. false positive, and I would like a solution like this to type narrow

Describe alternatives you've considered

const dfd = require("danfojs-node");

const json_data = [
  { A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
  { A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
  { A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
  { A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 },
];

const df = new dfd.DataFrame(json_data)
const multiMetricDf = dfd.concat({
  dfList: [df, df],
  axis: 0,
})
multiMetricDf instanceof dfd.DataFrame // returns False

The above code snippet returns False

If there was a method to convert Series to DataFrame (#619) that would be a suitable workaround

Additional context

For working with Danfo, I think such type narrowing is essential

const dfd = require("danfojs-node");


function logPrototypeNames(obj: any): void {
  let proto = Object.getPrototypeOf(obj);

  while (proto) {
      console.log(`Prototype constructor name: ${proto.constructor.name}`);
      proto = Object.getPrototypeOf(proto);
  }
}

const json_data = [
  { A: 0.4612, B: 4.28283, C: -1.509, D: -1.1352 },
  { A: 0.5112, B: -0.22863, C: -3.39059, D: 1.1632 },
  { A: 0.6911, B: -0.82863, C: -1.5059, D: 2.1352 },
  { A: 0.4692, B: -1.28863, C: 4.5059, D: 4.1632 },
];
const df = new dfd.DataFrame(json_data)

console.log("df is instance of DataFrame:", df instanceof dfd.DataFrame);

logPrototypeNames(df);
console.log()

const multiMetricDf = dfd.concat({
  dfList: [df, df],
  axis: 0,
})
multiMetricDf instanceof dfd.DataFrame

console.log("multiMetricDf is NOT instance of DataFrame:", multiMetricDf instanceof dfd.DataFrame);

logPrototypeNames(multiMetricDf);

console.log("here", multiMetricDf.ctypes)

Returns

df is instance of DataFrame: true
Prototype constructor name: DataFrame
Prototype constructor name: DataFrame
Prototype constructor name: NDframe
Prototype constructor name: Object

multiMetricDf is NOT instance of DataFrame: false
Prototype constructor name: DataFrame
Prototype constructor name: NDframe
Prototype constructor name: Object

So not sure what the problem is here.

This is my current workaround:

/**
 * Allows type narrowing of Series to DataFrame
 * https://github.com/javascriptdata/danfojs/issues/640
 *
 * @param df - DataFrame or Series
 * @returns True if it has a ctypes attribute, expected on DataFrame but not Series
 */
function isDataFrame(df: unknown): df is dfd.DataFrame {
  if (df instanceof dfd.Series) {
    return false
  }
  if ((df as dfd.DataFrame).ctypes !== undefined) {
    // ctypes attribute only exists on DataFrame
    return true
  } else {
    return false
  }
}
@bml1g12
Copy link
Author

bml1g12 commented Apr 19, 2024

Maybe the issue is related to a difference between

import { DataFrame } from "danfojs-node/dist/danfojs-base"
import { DataFrame } from "danfojs-node"

which means that the latter is not equal to the former, and the former is returned in some cases, whereas the latter is imported by default

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant