Jak zmienić elementy iterowane? (generator)

0

Mamy klasę i osobną funkcję taką o:

import pandas as pd


class M:
   
    def __init__(self):
        self.k = pd.DataFrame({"a":[1,2,3], "b":[2,3,4]})
        self.v = pd.DataFrame({"aa":[11,22,33], "bb":[22,33,44]})
       
    def generator(self):
        for i in range(self.k.shape[1]):
            yield self.k.iloc[:, i], self.v.iloc[:, i]


def transform(k, v):
    """
    crazy function
    """
    # complicated algorithm here...
    # ...
    # then:
    return k

Chcę przeiterować generatorem klasę i na każdej iteracji nadpisać element klasy:

m = M()
for k, v in m.generator():
    if k.sum() < 100:
        v = transform(k, v)
display(m.k)
display(m.v)

Niestety m.k i m.v pzoostają bez zmian:

self.k = pd.DataFrame({"a":[1,2,3], "b":[2,3,4]})
self.v = pd.DataFrame({"aa":[11,22,33], "bb":[22,33,44]})

a chcę by po przeiterowaniu było:

self.k = pd.DataFrame({"a":[1,2,3], "b":[2,3,4]})
self.v = pd.DataFrame({"a":[1,2,3], "b":[2,3,4]})

0

https://stackoverflow.com/questions/19290762/cant-modify-list-elements-in-a-loop-python

Prędzej m.k = transform(k, v) w środku listy. Ale uważałbym z nadpisywaniem listy, którą właśnie iterujesz. Oczywiście zastanowiłbym się co chcesz osiągnąć i czy nie da się tego zrobić wydajniej ;)

0

Nie za bardzo rozumiem co tutaj sie dzieje ale nic nie robisz z m.v wiec podmien

m = M()
for k, v in m.generator():
    if k.sum() < 100:
        v = transform(k, v)
display(m.k)
display(m.v)

na

m = M()
for k, v in m.generator():
    if k.sum() < 100:
        m.v = transform(k, v)
display(m.k)
display(m.v)

Plus tak jak wyżej nie zmieniaj pandasa w locie tylko zrob sobie kopie najpierw.

def transform(k, v):
    """
    crazy function
    """
    v = v.copy(deep=True)
    # complicated algorithm here...
    # ...
    # then:
    return v
0
komuher napisał(a):

podmien

m = M()
for k, v in m.generator():
    if k.sum() < 100:
        v = transform(k, v)
display(m.k)
display(m.v)

na

m = M()
for k, v in m.generator():
    if k.sum() < 100:
        m.v = transform(k, v)
display(m.k)
display(m.v)

ale wtedy zmieni mi nadpisze całe m.v a ja chcę zmieniać osobno każdą kolumnę m.v. v przy iterowaniu jest jedną kolumną, to jest series. A m.v to jest DataFrame.

Inaczej:

chcę coś takiego:

m = M()
for i in range(self.k.shape[1]):
    self.k.iloc[:, i], self.v.iloc[:, i]
    if self.k.iloc[:, i].sum() < 100:
        self.v.iloc[:, i] = transform(self.k.iloc[:, i], self.v.iloc[:, i])
display(m.k)
display(m.v)

tylko, że chcę użyć generatora.

moja próba:

m = M()
for k, v in m.generator():
    if k.sum() < 100:
        v = transform(k, v)
display(m.k)
display(m.v)
0

Inaczej:

chcę coś takiego:

m = M()
for i in range(self.k.shape[1]):
    self.k.iloc[:, i], self.v.iloc[:, i]
    if self.k.iloc[:, i].sum() < 100:
        self.v.iloc[:, i] = transform(self.k.iloc[:, i], self.v.iloc[:, i])
display(m.k)
display(m.v)

tylko, że chcę użyć generatora.

moja próba:

m = M()
for k, v in m.generator():
    if k.sum() < 100:
        v = transform(k, v)
display(m.k)
display(m.v)

Tak?

m = M()
for k, v in m.generator():
    if k.sum() < 100:
        m.v.iloc[:, i] = transform(k, v)
display(m.k)
display(m.v)

to że używasz generatora nie ma znaczenia przy zmienianiu wartości bardziej przy async/oszczedzaniu pamieci

0

No to inaczej. Nawet tam ten generator nie jest potrzebny. Zwłaszcza, że nie potrzebujesz v dla k.sum>100:

for i in range(m.k.shape[1]):
        temp_k = m.k.iloc[:, i]
        if temp_k.sum()<100:
            m.k.iloc[:, i] = transform(temp_k, m.v.iloc[:, i])

Tylko dobrac lepsze nazwy/dopisac metody dostępowe

1 użytkowników online, w tym zalogowanych: 0, gości: 1