@@ -1333,6 +1333,106 @@ export default class DataFrame extends NDframe implements DataFrameInterface {
13331333
13341334 }
13351335
1336+ /**
1337+ * Return difference of DataFrame with other.
1338+ * @param other DataFrame, Series, Array or Scalar number (positive numbers are preceding rows, negative are following rows) to compare difference with.
1339+ * @param options.axis 0 or 1. If 0, compute the difference column-wise, if 1, row-wise
1340+ * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false
1341+ * @example
1342+ * ```
1343+ * const df = new DataFrame([[1, 2, 3, 4, 5, 6], [1, 1, 2, 3, 5, 8], [1, 4, 9, 16, 25, 36]], { columns: ['A', 'B', 'C'] })
1344+ *
1345+ * // Difference with previous row
1346+ * const df0 = df.diff(1)
1347+ * console.log(df0)
1348+ *
1349+ * // Difference with previous column
1350+ * const df1 = df.diff(1, {axis: 0})
1351+ * console.log(df1)
1352+ *
1353+ * // Difference with previous 3rd previous row
1354+ * const df2 = df.diff(3)
1355+ * console.log(df2)
1356+ *
1357+ * // Difference with following row
1358+ * const df3 = df.diff(-1)
1359+ * console.log(df3)
1360+ *
1361+ * // Difference with another DataFrame
1362+ * const df4 = df.diff(df3)
1363+ * console.log(df4)
1364+ * ```
1365+ */
1366+ diff ( other : DataFrame | Series | number [ ] | number , options ?: { axis ?: 0 | 1 , inplace ?: boolean } ) : DataFrame
1367+ diff ( other : DataFrame | Series | number [ ] | number , options ?: { axis ?: 0 | 1 , inplace ?: boolean } ) : DataFrame | void {
1368+ const { inplace, axis } = { inplace : false , axis : 1 , ...options }
1369+
1370+ if ( this . $frameIsNotCompactibleForArithmeticOperation ( ) ) {
1371+ throw Error ( "TypeError: diff operation is not supported for string dtypes" ) ;
1372+ }
1373+
1374+ if ( [ 0 , 1 ] . indexOf ( axis ) === - 1 ) {
1375+ throw Error ( "ParamError: Axis must be 0 or 1" ) ;
1376+ }
1377+
1378+ if ( other === 0 ) {
1379+ return this ;
1380+ }
1381+
1382+ if ( typeof other === "number" && axis === 1 ) {
1383+ const orig_tensor = this . tensor . clone ( ) ;
1384+ let unit = [ NaN ] ;
1385+ for ( let i = 1 ; i < orig_tensor . shape [ orig_tensor . rank - 1 ] ; i ++ ) {
1386+ unit . push ( NaN ) ;
1387+ }
1388+ let diff_array : any [ ] = orig_tensor . arraySync ( ) ;
1389+ if ( other > 0 ) {
1390+ for ( let i = 0 ; i < other ; i ++ ) {
1391+ diff_array . unshift ( unit ) ;
1392+ diff_array . pop ( ) ;
1393+ }
1394+ }
1395+ else if ( other < 0 ) {
1396+ for ( let i = 0 ; i > other ; i -- ) {
1397+ diff_array . push ( unit ) ;
1398+ diff_array . shift ( ) ;
1399+ }
1400+ }
1401+ const diff_tensor = tensorflow . tensor2d ( diff_array , orig_tensor . shape ) ;
1402+ return this . $MathOps ( [ orig_tensor , diff_tensor ] , "sub" , inplace ) ;
1403+ }
1404+
1405+ if ( typeof other === "number" && axis === 0 ) {
1406+ const orig_df = new DataFrame ( this . tensor . clone ( ) ) ;
1407+ const orig_tensor = orig_df . T . tensor . clone ( ) ;
1408+ let unit = [ NaN ] ;
1409+ for ( let i = 1 ; i < orig_tensor . shape [ orig_tensor . rank - 1 ] ; i ++ ) {
1410+ unit . push ( NaN ) ;
1411+ }
1412+ let diff_array : any [ ] = orig_tensor . arraySync ( ) ;
1413+ if ( other > 0 ) {
1414+ for ( let i = 0 ; i < other ; i ++ ) {
1415+ diff_array . unshift ( unit ) ;
1416+ diff_array . pop ( ) ;
1417+ }
1418+ }
1419+ else if ( other < 0 ) {
1420+ for ( let i = 0 ; i > other ; i -- ) {
1421+ diff_array . push ( unit ) ;
1422+ diff_array . shift ( ) ;
1423+ }
1424+ }
1425+ const diff_tensor = tensorflow . tensor2d ( diff_array , orig_tensor . shape ) ;
1426+ const diff_df = this . $MathOps ( [ orig_tensor , diff_tensor ] , "sub" , inplace ) as DataFrame ;
1427+ return diff_df . T ;
1428+ }
1429+
1430+ if ( other instanceof DataFrame || other instanceof Series ) {
1431+ const tensors = this . $getTensorsForArithmeticOperationByAxis ( other , axis ) ;
1432+ return this . $MathOps ( tensors , "sub" , inplace ) ;
1433+ }
1434+ }
1435+
13361436 /**
13371437 * Return the absolute value of elements in a DataFrame.
13381438 * @param options.inplace Boolean indicating whether to perform the operation inplace or not. Defaults to false
0 commit comments