2626import traceback
2727import typing
2828from typing import (
29+ Any ,
2930 Callable ,
3031 Dict ,
3132 Hashable ,
9192 import bigframes .session
9293
9394 SingleItemValue = Union [bigframes .series .Series , int , float , str , Callable ]
95+ MultiItemValue = Union ["DataFrame" , Sequence [int | float | str | Callable ]]
9496
9597LevelType = typing .Hashable
9698LevelsType = typing .Union [LevelType , typing .Sequence [LevelType ]]
@@ -884,8 +886,13 @@ def __delitem__(self, key: str):
884886 df = self .drop (columns = [key ])
885887 self ._set_block (df ._get_block ())
886888
887- def __setitem__ (self , key : str , value : SingleItemValue ):
888- df = self ._assign_single_item (key , value )
889+ def __setitem__ (
890+ self , key : str | list [str ], value : SingleItemValue | MultiItemValue
891+ ):
892+ if isinstance (key , list ):
893+ df = self ._assign_multi_items (key , value )
894+ else :
895+ df = self ._assign_single_item (key , value )
889896 self ._set_block (df ._get_block ())
890897
891898 __setitem__ .__doc__ = inspect .getdoc (vendored_pandas_frame .DataFrame .__setitem__ )
@@ -2212,7 +2219,7 @@ def assign(self, **kwargs) -> DataFrame:
22122219 def _assign_single_item (
22132220 self ,
22142221 k : str ,
2215- v : SingleItemValue ,
2222+ v : SingleItemValue | MultiItemValue ,
22162223 ) -> DataFrame :
22172224 if isinstance (v , bigframes .series .Series ):
22182225 return self ._assign_series_join_on_index (k , v )
@@ -2230,7 +2237,33 @@ def _assign_single_item(
22302237 elif utils .is_list_like (v ):
22312238 return self ._assign_single_item_listlike (k , v )
22322239 else :
2233- return self ._assign_scalar (k , v )
2240+ return self ._assign_scalar (k , v ) # type: ignore
2241+
2242+ def _assign_multi_items (
2243+ self ,
2244+ k : list [str ],
2245+ v : SingleItemValue | MultiItemValue ,
2246+ ) -> DataFrame :
2247+ value_sources : Sequence [Any ] = []
2248+ if isinstance (v , DataFrame ):
2249+ value_sources = [v [col ] for col in v .columns ]
2250+ elif isinstance (v , bigframes .series .Series ):
2251+ # For behavior consistency with Pandas.
2252+ raise ValueError ("Columns must be same length as key" )
2253+ elif isinstance (v , Sequence ):
2254+ value_sources = v
2255+ else :
2256+ # We assign the same scalar value to all target columns.
2257+ value_sources = [v ] * len (k )
2258+
2259+ if len (value_sources ) != len (k ):
2260+ raise ValueError ("Columns must be same length as key" )
2261+
2262+ # Repeatedly assign columns in order.
2263+ result = self ._assign_single_item (k [0 ], value_sources [0 ])
2264+ for target , source in zip (k [1 :], value_sources [1 :]):
2265+ result = result ._assign_single_item (target , source )
2266+ return result
22342267
22352268 def _assign_single_item_listlike (self , k : str , v : Sequence ) -> DataFrame :
22362269 given_rows = len (v )
0 commit comments