列表理解几个框架
List comprehension several frames
我会使用 pd.DataFrames 来问这个问题,因为问题是在与他们合作时出现的。但它可能会泛化为 python.
中的可变变量
我想创建一个具有不同值的 DataFrame 列表。
目前我这样做:
data = pd.DataFrame(np.full((2, 2), 0), columns=['A', 'B'])
list_of_frames = []
for i in range(3):
tmp = data.copy()
tmp.loc[0, 'A'] = i
list_of_frames.append(tmp)
第一个问题是这个pythonic?感觉很丑。
我真的很想把这个写成列表理解。
例如像这样:
[data.loc_set_copy([0, 'A'], i) for i in range(3)]
由于我目前正在 pd.DataFrame 之上使用 classes 开发自己的模块,因此我考虑在自己的 class 中实现此方法。
我的 class 是围绕 pd.DataFrame 编写的, 没有继承 pd.DataFrame 的 。
它为许多 DataFrame 方法提供包装器,尤其是 loc
和 iloc
,它们的行为方式与您从 pd.DataFrames
中了解到的相同。
现在我有两个解决方案:
正常方法
def loc_set_copy(self, key, value):
new = self.copy()
new.loc[key[0], key[1]] = value
return new
这允许:
[instance_of_my_class.loc_set_copy([0, 'A'], i) for i in range(3)]
问题是不支持切片。
因此,如果我想更改整个列:
[instance_of_my_class.loc_set_copy([:, 'A'], i) for i in range(3)]
我得到一个 SyntaxError
.
疯狂的解决方法
我定义了以下助手class:
class _Loc_Set_Copy():
def __init__(self, molecule):
self.data = data
def __getitem__(self, key):
new = self.data.copy()
new.loc[key[0], key[1]] = key[2]
return new
在我的 class 定义中我有:
class my_class():
def __init__(self):
self.loc_set_copy = _Loc_Set_Copy(self)
现在我可以使用:
[instance_of_my_class.loc_set_copy[:, 'A', i] for i in range(3)]
我知道这是对语法的滥用。有什么可能的方法可以干净利落地做到这一点,还是我应该在开始时只依赖 for 循环?
当然可以传递 slice
,使用 slice
对象:
>>> [loc_set_copy(data, [slice(None), 'A'], i) for i in range(3)]
[ A B
0 0 0.0
1 0 0.0, A B
0 1 0.0
1 1 0.0, A B
0 2 0.0
1 2 0.0]
更漂亮:
>>> from pprint import pprint
>>> pprint([loc_set_copy(data, [slice(None), 'A'], i) for i in range(3)])
[ A B
0 0 0.0
1 0 0.0,
A B
0 1 0.0
1 1 0.0,
A B
0 2 0.0
1 2 0.0]
>>>
注:
>>> data.loc[:, 'A']
0 0.0
1 0.0
Name: A, dtype: float64
>>> data.loc[slice(None), 'A']
0 0.0
1 0.0
Name: A, dtype: float64
本质上,切片符号是将 slice
对象传递给 __getitem__
的语法糖:
>>> x = list(range(22))
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
>>> x[0:10:2]
[0, 2, 4, 6, 8]
>>> x[slice(0,10,2)]
[0, 2, 4, 6, 8]
>>> x.__getitem__(slice(0,10,2))
[0, 2, 4, 6, 8]
>>>
注意,鉴于上述情况,您可以将方法简化为:
>>> def loc_set_copy(self, key, value):
... new = self.copy()
... new.loc[key] = value
... return new
...
如果你小心为key
参数传递tuple
s:
>>> pprint([loc_set_copy(data, (0, 'A'), i) for i in range(3)])
[ A B
0 0.0 0.0
1 0.0 0.0,
A B
0 1.0 0.0
1 0.0 0.0,
A B
0 2.0 0.0
1 0.0 0.0]
>>> pprint([loc_set_copy(data, (slice(None), 'A'), i) for i in range(3)])
[ A B
0 0 0.0
1 0 0.0,
A B
0 1 0.0
1 1 0.0,
A B
0 2 0.0
1 2 0.0]
>>>
以下内容现在应该很有意义了:
>>> class A:
... def __getitem__(self, key):
... print(type(key))
... print(key)
...
>>> a = A()
>>> a[1]
<class 'int'>
1
>>> a[[1]]
<class 'list'>
[1]
>>> a[object()]
<class 'object'>
<object object at 0x1003932e0>
>>>
>>> a[:1]
<class 'slice'>
slice(None, 1, None)
>>> a[:]
<class 'slice'>
slice(None, None, None)
>>> a[:,:,1:4]
<class 'tuple'>
(slice(None, None, None), slice(None, None, None), slice(1, 4, None))
>>> a[:,:,[1,2]]
<class 'tuple'>
(slice(None, None, None), slice(None, None, None), [1, 2])
>>> a[:,object():,[1,2]]
<class 'tuple'>
(slice(None, None, None), slice(<object object at 0x1003932e0>, None, None), [1, 2])
>>>
我会使用 pd.DataFrames 来问这个问题,因为问题是在与他们合作时出现的。但它可能会泛化为 python.
中的可变变量我想创建一个具有不同值的 DataFrame 列表。 目前我这样做:
data = pd.DataFrame(np.full((2, 2), 0), columns=['A', 'B'])
list_of_frames = []
for i in range(3):
tmp = data.copy()
tmp.loc[0, 'A'] = i
list_of_frames.append(tmp)
第一个问题是这个pythonic?感觉很丑。
我真的很想把这个写成列表理解。 例如像这样:
[data.loc_set_copy([0, 'A'], i) for i in range(3)]
由于我目前正在 pd.DataFrame 之上使用 classes 开发自己的模块,因此我考虑在自己的 class 中实现此方法。
我的 class 是围绕 pd.DataFrame 编写的, 没有继承 pd.DataFrame 的 。
它为许多 DataFrame 方法提供包装器,尤其是 loc
和 iloc
,它们的行为方式与您从 pd.DataFrames
中了解到的相同。
现在我有两个解决方案:
正常方法
def loc_set_copy(self, key, value):
new = self.copy()
new.loc[key[0], key[1]] = value
return new
这允许:
[instance_of_my_class.loc_set_copy([0, 'A'], i) for i in range(3)]
问题是不支持切片。 因此,如果我想更改整个列:
[instance_of_my_class.loc_set_copy([:, 'A'], i) for i in range(3)]
我得到一个 SyntaxError
.
疯狂的解决方法
我定义了以下助手class:
class _Loc_Set_Copy():
def __init__(self, molecule):
self.data = data
def __getitem__(self, key):
new = self.data.copy()
new.loc[key[0], key[1]] = key[2]
return new
在我的 class 定义中我有:
class my_class():
def __init__(self):
self.loc_set_copy = _Loc_Set_Copy(self)
现在我可以使用:
[instance_of_my_class.loc_set_copy[:, 'A', i] for i in range(3)]
我知道这是对语法的滥用。有什么可能的方法可以干净利落地做到这一点,还是我应该在开始时只依赖 for 循环?
当然可以传递 slice
,使用 slice
对象:
>>> [loc_set_copy(data, [slice(None), 'A'], i) for i in range(3)]
[ A B
0 0 0.0
1 0 0.0, A B
0 1 0.0
1 1 0.0, A B
0 2 0.0
1 2 0.0]
更漂亮:
>>> from pprint import pprint
>>> pprint([loc_set_copy(data, [slice(None), 'A'], i) for i in range(3)])
[ A B
0 0 0.0
1 0 0.0,
A B
0 1 0.0
1 1 0.0,
A B
0 2 0.0
1 2 0.0]
>>>
注:
>>> data.loc[:, 'A']
0 0.0
1 0.0
Name: A, dtype: float64
>>> data.loc[slice(None), 'A']
0 0.0
1 0.0
Name: A, dtype: float64
本质上,切片符号是将 slice
对象传递给 __getitem__
的语法糖:
>>> x = list(range(22))
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
>>> x[0:10:2]
[0, 2, 4, 6, 8]
>>> x[slice(0,10,2)]
[0, 2, 4, 6, 8]
>>> x.__getitem__(slice(0,10,2))
[0, 2, 4, 6, 8]
>>>
注意,鉴于上述情况,您可以将方法简化为:
>>> def loc_set_copy(self, key, value):
... new = self.copy()
... new.loc[key] = value
... return new
...
如果你小心为key
参数传递tuple
s:
>>> pprint([loc_set_copy(data, (0, 'A'), i) for i in range(3)])
[ A B
0 0.0 0.0
1 0.0 0.0,
A B
0 1.0 0.0
1 0.0 0.0,
A B
0 2.0 0.0
1 0.0 0.0]
>>> pprint([loc_set_copy(data, (slice(None), 'A'), i) for i in range(3)])
[ A B
0 0 0.0
1 0 0.0,
A B
0 1 0.0
1 1 0.0,
A B
0 2 0.0
1 2 0.0]
>>>
以下内容现在应该很有意义了:
>>> class A:
... def __getitem__(self, key):
... print(type(key))
... print(key)
...
>>> a = A()
>>> a[1]
<class 'int'>
1
>>> a[[1]]
<class 'list'>
[1]
>>> a[object()]
<class 'object'>
<object object at 0x1003932e0>
>>>
>>> a[:1]
<class 'slice'>
slice(None, 1, None)
>>> a[:]
<class 'slice'>
slice(None, None, None)
>>> a[:,:,1:4]
<class 'tuple'>
(slice(None, None, None), slice(None, None, None), slice(1, 4, None))
>>> a[:,:,[1,2]]
<class 'tuple'>
(slice(None, None, None), slice(None, None, None), [1, 2])
>>> a[:,object():,[1,2]]
<class 'tuple'>
(slice(None, None, None), slice(<object object at 0x1003932e0>, None, None), [1, 2])
>>>