@@ -261,6 +261,18 @@ describe("expr", () => {
261
261
const actual = df . select ( col ( "nrs" ) . explode ( ) ) ;
262
262
expect ( actual ) . toFrameEqual ( expected ) ;
263
263
} ) ;
264
+ test ( "implode" , ( ) => {
265
+ const df = pl . DataFrame ( {
266
+ nrs : [ 1 , 2 , 1 , 3 ] ,
267
+ strs : [ "a" , "b" , null , "d" ] ,
268
+ } ) ;
269
+ const expected = pl . DataFrame ( {
270
+ nrs : [ [ 1 , 2 , 1 , 3 ] ] ,
271
+ strs : [ [ "a" , "b" , null , "d" ] ] ,
272
+ } ) ;
273
+ const actual = df . select ( col ( "nrs" ) . implode ( ) , col ( "strs" ) . implode ( ) ) ;
274
+ expect ( actual ) . toFrameEqual ( expected ) ;
275
+ } ) ;
264
276
test ( "extend" , ( ) => {
265
277
const df = pl . DataFrame ( {
266
278
a : [ 1 , 2 , 3 , 4 , 5 ] ,
@@ -1075,6 +1087,56 @@ describe("expr.str", () => {
1075
1087
) ;
1076
1088
expect ( actual ) . toFrameEqual ( expected ) ;
1077
1089
} ) ;
1090
+ test ( "endsWith" , ( ) => {
1091
+ const df = pl . DataFrame ( {
1092
+ fruits : [ "apple" , "mango" , null ] ,
1093
+ } ) ;
1094
+ const expected = df . withColumn (
1095
+ pl . Series ( "has_suffix" , [ false , true , null ] , pl . Bool ) ,
1096
+ ) ;
1097
+ const actual = df . withColumn (
1098
+ col ( "fruits" ) . str . endsWith ( "go" ) . as ( "has_suffix" ) ,
1099
+ ) ;
1100
+ expect ( actual ) . toFrameEqual ( expected ) ;
1101
+ } ) ;
1102
+ test ( "endsWith:expr" , ( ) => {
1103
+ const df = pl . DataFrame ( {
1104
+ fruits : [ "apple" , "mango" , "banana" ] ,
1105
+ suffix : [ "le" , "go" , "nu" ] ,
1106
+ } ) ;
1107
+ const expected = df . withColumn (
1108
+ pl . Series ( "has_suffix" , [ true , true , false ] , pl . Bool ) ,
1109
+ ) ;
1110
+ const actual = df . withColumn (
1111
+ col ( "fruits" ) . str . endsWith ( pl . col ( "suffix" ) ) . as ( "has_suffix" ) ,
1112
+ ) ;
1113
+ expect ( actual ) . toFrameEqual ( expected ) ;
1114
+ } ) ;
1115
+ test ( "startsWith" , ( ) => {
1116
+ const df = pl . DataFrame ( {
1117
+ fruits : [ "apple" , "mango" , null ] ,
1118
+ } ) ;
1119
+ const expected = df . withColumn (
1120
+ pl . Series ( "has_prefix" , [ true , false , null ] , pl . Bool ) ,
1121
+ ) ;
1122
+ const actual = df . withColumn (
1123
+ col ( "fruits" ) . str . startsWith ( "app" ) . as ( "has_prefix" ) ,
1124
+ ) ;
1125
+ expect ( actual ) . toFrameEqual ( expected ) ;
1126
+ } ) ;
1127
+ test ( "startsWith:expr" , ( ) => {
1128
+ const df = pl . DataFrame ( {
1129
+ fruits : [ "apple" , "mango" , "banana" ] ,
1130
+ prefix : [ "app" , "na" , "ba" ] ,
1131
+ } ) ;
1132
+ const expected = df . withColumn (
1133
+ pl . Series ( "has_prefix" , [ true , false , true ] , pl . Bool ) ,
1134
+ ) ;
1135
+ const actual = df . withColumn (
1136
+ col ( "fruits" ) . str . startsWith ( pl . col ( "prefix" ) ) . as ( "has_prefix" ) ,
1137
+ ) ;
1138
+ expect ( actual ) . toFrameEqual ( expected ) ;
1139
+ } ) ;
1078
1140
test ( "split" , ( ) => {
1079
1141
const df = pl . DataFrame ( { a : [ "ab,cd" , "e,fg" , "h" ] } ) ;
1080
1142
const expected = pl . DataFrame ( {
@@ -1196,10 +1258,10 @@ describe("expr.str", () => {
1196
1258
} ) ;
1197
1259
test ( "str.replace" , ( ) => {
1198
1260
const df = pl . DataFrame ( {
1199
- os : [ "kali-linux" , "debian-linux" , "ubuntu-linux" , "mac-sierra" ] ,
1261
+ os : [ "kali-linux" , "debian-linux" , null , "mac-sierra" ] ,
1200
1262
} ) ;
1201
1263
const expected = pl . DataFrame ( {
1202
- os : [ "kali:linux" , "debian:linux" , "ubuntu:linux" , "mac:sierra" ] ,
1264
+ os : [ "kali:linux" , "debian:linux" , null , "mac:sierra" ] ,
1203
1265
} ) ;
1204
1266
const seriesActual = df
1205
1267
. getColumn ( "os" )
@@ -1210,6 +1272,48 @@ describe("expr.str", () => {
1210
1272
expect ( actual ) . toFrameEqual ( expected ) ;
1211
1273
expect ( seriesActual ) . toFrameEqual ( expected ) ;
1212
1274
} ) ;
1275
+ test ( "str.replace:Expr1" , ( ) => {
1276
+ const df = pl . DataFrame ( {
1277
+ os : [ "kali-linux" , "debian-linux" , null , "mac-sierra" ] ,
1278
+ val : [ "windows" , "acorn" , "atari" , null ] ,
1279
+ } ) ;
1280
+ const expected = pl . DataFrame ( {
1281
+ os : [ "kali-windows" , "debian-acorn" , null , null ] ,
1282
+ } ) ;
1283
+ const actual = df . select (
1284
+ col ( "os" ) . str . replace ( "linux" , col ( "val" ) ) . as ( "os" ) ,
1285
+ ) ;
1286
+ expect ( actual ) . toFrameEqual ( expected ) ;
1287
+ } ) ;
1288
+ test ( "str.replace:Expr2" , ( ) => {
1289
+ const df = pl . DataFrame ( {
1290
+ cost : [ "#12.34" , "#56.78" ] ,
1291
+ text : [ "123abc" , "abc456" ] ,
1292
+ } ) ;
1293
+ const expected = pl . DataFrame ( {
1294
+ expr : [ "123#12.34" , "#56.78456" ] ,
1295
+ } ) ;
1296
+ const actual = df . select (
1297
+ col ( "text" ) . str . replace ( "abc" , pl . col ( "cost" ) ) . alias ( "expr" ) ,
1298
+ ) ;
1299
+ expect ( actual ) . toFrameEqual ( expected ) ;
1300
+ } ) ;
1301
+ // TODO: Remove skip when polars-plan will support for "dynamic pattern length in 'str.replace' expressions"
1302
+ test . skip ( "str.replace:Expr3" , ( ) => {
1303
+ const df = pl . DataFrame ( {
1304
+ os : [ "kali-linux" , "debian-linux" , "ubuntu-linux" , "mac-sierra" ] ,
1305
+ pat : [ "linux" , "linux" , "linux" , "mac" ] ,
1306
+ val : [ "windows" , "acorn" , "atari" , "arm" ] ,
1307
+ } ) ;
1308
+ const expected = pl . DataFrame ( {
1309
+ os : [ "kali-windows" , "debian-acorn" , "ubuntu-atari" , "arm-sierra" ] ,
1310
+ } ) ;
1311
+ const actual = df . select (
1312
+ col ( "os" ) . str . replace ( col ( "pat" ) , col ( "val" ) ) . as ( "os" ) ,
1313
+ ) ;
1314
+ expect ( actual ) . toFrameEqual ( expected ) ;
1315
+ } ) ;
1316
+
1213
1317
test ( "str.replaceAll" , ( ) => {
1214
1318
const df = pl . DataFrame ( {
1215
1319
os : [
@@ -1236,6 +1340,108 @@ describe("expr.str", () => {
1236
1340
expect ( actual ) . toFrameEqual ( expected ) ;
1237
1341
expect ( seriesActual ) . toFrameEqual ( expected ) ;
1238
1342
} ) ;
1343
+ test ( "str.replaceAll:Expr" , ( ) => {
1344
+ const df = pl . DataFrame ( {
1345
+ os : [
1346
+ "kali-linux-2021.3a" ,
1347
+ null ,
1348
+ "ubuntu-linux-16.04" ,
1349
+ "mac-sierra-10.12.1" ,
1350
+ ] ,
1351
+ val : [ ":" , ":" , null , "_" ] ,
1352
+ } ) ;
1353
+ const expected = pl . DataFrame ( {
1354
+ os : [ "kali:linux:2021.3a" , null , null , "mac_sierra_10.12.1" ] ,
1355
+ } ) ;
1356
+ const actual = df . select (
1357
+ col ( "os" ) . str . replaceAll ( "-" , col ( "val" ) ) . as ( "os" ) ,
1358
+ ) ;
1359
+ expect ( actual ) . toFrameEqual ( expected ) ;
1360
+ } ) ;
1361
+ // TODO: Remove skip when polars-plan will support for "dynamic pattern length in 'str.replace' expressions"
1362
+ test . skip ( "str.replaceAll:Expr2" , ( ) => {
1363
+ const df = pl . DataFrame ( {
1364
+ os : [
1365
+ "kali-linux-2021.3a" ,
1366
+ null ,
1367
+ "ubuntu-linux-16.04" ,
1368
+ "mac-sierra-10.12.1" ,
1369
+ ] ,
1370
+ pat : [ "-" , "-" , "-" , "." ] ,
1371
+ val : [ ":" , ":" , null , "_" ] ,
1372
+ } ) ;
1373
+ const expected = pl . DataFrame ( {
1374
+ os : [ "kali:linux:2021.3a" , null , null , "mac-sierra-10_12_1" ] ,
1375
+ } ) ;
1376
+ const actual = df . select (
1377
+ col ( "os" ) . str . replaceAll ( col ( "pat" ) , col ( "val" ) ) . as ( "os" ) ,
1378
+ ) ;
1379
+ expect ( actual ) . toFrameEqual ( expected ) ;
1380
+ } ) ;
1381
+ test ( "struct:field" , ( ) => {
1382
+ const df = pl . DataFrame ( {
1383
+ objs : [
1384
+ { a : 1 , b : 2.0 , c : "abc" } ,
1385
+ { a : 10 , b : 20.0 , c : "def" } ,
1386
+ ] ,
1387
+ } ) ;
1388
+ const expected = pl . DataFrame ( {
1389
+ b : [ 2.0 , 20.0 ] ,
1390
+ last : [ "abc" , "def" ] ,
1391
+ } ) ;
1392
+ const actual = df . select (
1393
+ col ( "objs" ) . struct . field ( "b" ) ,
1394
+ col ( "objs" ) . struct . field ( "c" ) . as ( "last" ) ,
1395
+ ) ;
1396
+ expect ( actual ) . toFrameStrictEqual ( expected ) ;
1397
+ } ) ;
1398
+ test ( "struct:nth" , ( ) => {
1399
+ const df = pl . DataFrame ( {
1400
+ objs : [
1401
+ { a : 1 , b : 2.0 , c : "abc" } ,
1402
+ { a : 10 , b : 20.0 , c : "def" } ,
1403
+ ] ,
1404
+ } ) ;
1405
+ const expected = pl . DataFrame ( {
1406
+ b : [ 2.0 , 20.0 ] ,
1407
+ last : [ "abc" , "def" ] ,
1408
+ } ) ;
1409
+ const actual = df . select (
1410
+ col ( "objs" ) . struct . nth ( 1 ) ,
1411
+ col ( "objs" ) . struct . nth ( 2 ) . as ( "last" ) ,
1412
+ ) ;
1413
+ expect ( actual ) . toFrameStrictEqual ( expected ) ;
1414
+ } ) ;
1415
+ test ( "struct:withFields" , ( ) => {
1416
+ const df = pl . DataFrame ( {
1417
+ objs : [
1418
+ { a : 1 , b : 2.0 , c : "abc" } ,
1419
+ { a : 10 , b : 20.0 , c : "def" } ,
1420
+ ] ,
1421
+ more : [ "text1" , "text2" ] ,
1422
+ final : [ 100 , null ] ,
1423
+ } ) ;
1424
+ const expected = pl . DataFrame ( {
1425
+ objs : [
1426
+ { a : 1 , b : 2.0 , c : "abc" , d : null , e : "text" } ,
1427
+ { a : 10 , b : 20.0 , c : "def" , d : null , e : "text" } ,
1428
+ ] ,
1429
+ new : [
1430
+ { a : 1 , b : 2.0 , c : "abc" , more : "text1" , final : 100 } ,
1431
+ { a : 10 , b : 20.0 , c : "def" , more : "text2" , final : null } ,
1432
+ ] ,
1433
+ } ) ;
1434
+ const actual = df . select (
1435
+ col ( "objs" ) . struct . withFields ( [
1436
+ pl . lit ( null ) . alias ( "d" ) ,
1437
+ pl . lit ( "text" ) . alias ( "e" ) ,
1438
+ ] ) ,
1439
+ col ( "objs" )
1440
+ . struct . withFields ( [ col ( "more" ) , col ( "final" ) ] )
1441
+ . alias ( "new" ) ,
1442
+ ) ;
1443
+ expect ( actual ) . toFrameStrictEqual ( expected ) ;
1444
+ } ) ;
1239
1445
test ( "expr.replace" , ( ) => {
1240
1446
const df = pl . DataFrame ( { a : [ 1 , 2 , 2 , 3 ] , b : [ "a" , "b" , "c" , "d" ] } ) ;
1241
1447
{
@@ -1443,6 +1649,63 @@ describe("expr.str", () => {
1443
1649
expect ( actual ) . toFrameEqual ( expected ) ;
1444
1650
expect ( seriesActual ) . toFrameEqual ( expected ) ;
1445
1651
} ) ;
1652
+
1653
+ test ( "stripChars:Expr" , ( ) => {
1654
+ const df = pl . DataFrame ( {
1655
+ os : [
1656
+ "#Kali-Linux###" ,
1657
+ "$$$Debian-Linux$" ,
1658
+ null ,
1659
+ "Ubuntu-Linux " ,
1660
+ " Mac-Sierra" ,
1661
+ ] ,
1662
+ chars : [ "#" , "$" , " " , " " , null ] ,
1663
+ } ) ;
1664
+ const expected = pl . DataFrame ( {
1665
+ os : [ "Kali-Linux" , "Debian-Linux" , null , "Ubuntu-Linux" , "Mac-Sierra" ] ,
1666
+ } ) ;
1667
+ const actual = df . select ( col ( "os" ) . str . stripChars ( col ( "chars" ) ) . as ( "os" ) ) ;
1668
+ expect ( actual ) . toFrameEqual ( expected ) ;
1669
+ } ) ;
1670
+ test ( "stripCharsStart:Expr" , ( ) => {
1671
+ const df = pl . DataFrame ( {
1672
+ os : [
1673
+ "#Kali-Linux###" ,
1674
+ "$$$Debian-Linux$" ,
1675
+ null ,
1676
+ " Ubuntu-Linux " ,
1677
+ "Mac-Sierra" ,
1678
+ ] ,
1679
+ chars : [ "#" , "$" , " " , null , "Mac-" ] ,
1680
+ } ) ;
1681
+ const expected = pl . DataFrame ( {
1682
+ os : [ "Kali-Linux###" , "Debian-Linux$" , null , "Ubuntu-Linux " , "Sierra" ] ,
1683
+ } ) ;
1684
+ const actual = df . select (
1685
+ col ( "os" ) . str . stripCharsStart ( col ( "chars" ) ) . as ( "os" ) ,
1686
+ ) ;
1687
+ expect ( actual ) . toFrameEqual ( expected ) ;
1688
+ } ) ;
1689
+ test ( "stripCharsEnd:Expr" , ( ) => {
1690
+ const df = pl . DataFrame ( {
1691
+ os : [
1692
+ "#Kali-Linux###" ,
1693
+ "$$$Debian-Linux$" ,
1694
+ null ,
1695
+ "Ubuntu-Linux " ,
1696
+ " Mac-Sierra" ,
1697
+ ] ,
1698
+ chars : [ "#" , "$" , " " , null , "-Sierra" ] ,
1699
+ } ) ;
1700
+ const expected = pl . DataFrame ( {
1701
+ os : [ "#Kali-Linux" , "$$$Debian-Linux" , null , "Ubuntu-Linux" , " Mac" ] ,
1702
+ } ) ;
1703
+ const actual = df . select (
1704
+ col ( "os" ) . str . stripCharsEnd ( col ( "chars" ) ) . as ( "os" ) ,
1705
+ ) ;
1706
+ expect ( actual ) . toFrameEqual ( expected ) ;
1707
+ } ) ;
1708
+
1446
1709
test ( "padStart" , ( ) => {
1447
1710
const df = pl . DataFrame ( {
1448
1711
foo : [ "a" , "b" , "cow" , "longer" ] ,
0 commit comments