Is there a limit for zip() elements in loops in python?











up vote
0
down vote

favorite












Something weird happened to me today. I needed to create a list based on a sequence of if statements. My dataframe looks something like this:



prom_lect4b_rbd    prom_lect2m_rbd   prom_lect8b_rbd   prom_lect6b_rbd
100 np.nan 80 200
np.nan np.nan 40 1000
np.nan np.nan np.nan 90
230 100 80 100


Columns are orderer according to their priority. The list (or column) I'm trying to create takes the first value from those rows that is not nan. So, in this case I want a column that looks like this:



simce_final_lect
100
40
90
230


I tried the following:



cols=[simces.prom_lect4b_rbd, simces.prom_lect2m_rbd, simces.prom_lect8b_rbd, simces.prom_lect6b_rbd]

simce_final_lect=[j if np.isnan(j)==False else k if np.isnan(k)==False
else l if np.isnan(l)==False else m if np.isnan(m)==False
else np.nan for j,k,l,m in zip(cols[0],cols[1],cols[2],cols[3])]


And that just copies two values (out of 8752) to the list. But if I limit my zip to just j,k,l, it works perfectly:



simce_final_lect=[j if np.isnan(j)==False else k if np.isnan(k)==False
else l if np.isnan(l)==False
else np.nan for j,k,l in zip(cols[0],cols[1],cols[2])]


Do you know what is happening? Else, is there a more efficient solution to my problem?










share|improve this question


















  • 2




    Your last column is shorter than the others. zip stops when the shorter list ends. BTW: you should really consider extracting the expression that takes the value into a function: first_not_nan = lambda vals: next(x for x in vals if not math.isnan(x)) then result = list(map(first_not_nan, zip(A,B,C,D))).
    – Bakuriu
    Nov 8 at 19:25












  • Thanks Bakuriu! Could you explain me a little further your approach? I'm not really used to lambda expressions outside the apply function when trying to do an operation in every row of a Series. When I used both commands it got me a list of just 148 values. Maybe it stopped when it found a row consisting of only nan ? How could I fill it with a nan in that case? Thanks
    – Juan C
    Nov 8 at 19:35















up vote
0
down vote

favorite












Something weird happened to me today. I needed to create a list based on a sequence of if statements. My dataframe looks something like this:



prom_lect4b_rbd    prom_lect2m_rbd   prom_lect8b_rbd   prom_lect6b_rbd
100 np.nan 80 200
np.nan np.nan 40 1000
np.nan np.nan np.nan 90
230 100 80 100


Columns are orderer according to their priority. The list (or column) I'm trying to create takes the first value from those rows that is not nan. So, in this case I want a column that looks like this:



simce_final_lect
100
40
90
230


I tried the following:



cols=[simces.prom_lect4b_rbd, simces.prom_lect2m_rbd, simces.prom_lect8b_rbd, simces.prom_lect6b_rbd]

simce_final_lect=[j if np.isnan(j)==False else k if np.isnan(k)==False
else l if np.isnan(l)==False else m if np.isnan(m)==False
else np.nan for j,k,l,m in zip(cols[0],cols[1],cols[2],cols[3])]


And that just copies two values (out of 8752) to the list. But if I limit my zip to just j,k,l, it works perfectly:



simce_final_lect=[j if np.isnan(j)==False else k if np.isnan(k)==False
else l if np.isnan(l)==False
else np.nan for j,k,l in zip(cols[0],cols[1],cols[2])]


Do you know what is happening? Else, is there a more efficient solution to my problem?










share|improve this question


















  • 2




    Your last column is shorter than the others. zip stops when the shorter list ends. BTW: you should really consider extracting the expression that takes the value into a function: first_not_nan = lambda vals: next(x for x in vals if not math.isnan(x)) then result = list(map(first_not_nan, zip(A,B,C,D))).
    – Bakuriu
    Nov 8 at 19:25












  • Thanks Bakuriu! Could you explain me a little further your approach? I'm not really used to lambda expressions outside the apply function when trying to do an operation in every row of a Series. When I used both commands it got me a list of just 148 values. Maybe it stopped when it found a row consisting of only nan ? How could I fill it with a nan in that case? Thanks
    – Juan C
    Nov 8 at 19:35













up vote
0
down vote

favorite









up vote
0
down vote

favorite











Something weird happened to me today. I needed to create a list based on a sequence of if statements. My dataframe looks something like this:



prom_lect4b_rbd    prom_lect2m_rbd   prom_lect8b_rbd   prom_lect6b_rbd
100 np.nan 80 200
np.nan np.nan 40 1000
np.nan np.nan np.nan 90
230 100 80 100


Columns are orderer according to their priority. The list (or column) I'm trying to create takes the first value from those rows that is not nan. So, in this case I want a column that looks like this:



simce_final_lect
100
40
90
230


I tried the following:



cols=[simces.prom_lect4b_rbd, simces.prom_lect2m_rbd, simces.prom_lect8b_rbd, simces.prom_lect6b_rbd]

simce_final_lect=[j if np.isnan(j)==False else k if np.isnan(k)==False
else l if np.isnan(l)==False else m if np.isnan(m)==False
else np.nan for j,k,l,m in zip(cols[0],cols[1],cols[2],cols[3])]


And that just copies two values (out of 8752) to the list. But if I limit my zip to just j,k,l, it works perfectly:



simce_final_lect=[j if np.isnan(j)==False else k if np.isnan(k)==False
else l if np.isnan(l)==False
else np.nan for j,k,l in zip(cols[0],cols[1],cols[2])]


Do you know what is happening? Else, is there a more efficient solution to my problem?










share|improve this question













Something weird happened to me today. I needed to create a list based on a sequence of if statements. My dataframe looks something like this:



prom_lect4b_rbd    prom_lect2m_rbd   prom_lect8b_rbd   prom_lect6b_rbd
100 np.nan 80 200
np.nan np.nan 40 1000
np.nan np.nan np.nan 90
230 100 80 100


Columns are orderer according to their priority. The list (or column) I'm trying to create takes the first value from those rows that is not nan. So, in this case I want a column that looks like this:



simce_final_lect
100
40
90
230


I tried the following:



cols=[simces.prom_lect4b_rbd, simces.prom_lect2m_rbd, simces.prom_lect8b_rbd, simces.prom_lect6b_rbd]

simce_final_lect=[j if np.isnan(j)==False else k if np.isnan(k)==False
else l if np.isnan(l)==False else m if np.isnan(m)==False
else np.nan for j,k,l,m in zip(cols[0],cols[1],cols[2],cols[3])]


And that just copies two values (out of 8752) to the list. But if I limit my zip to just j,k,l, it works perfectly:



simce_final_lect=[j if np.isnan(j)==False else k if np.isnan(k)==False
else l if np.isnan(l)==False
else np.nan for j,k,l in zip(cols[0],cols[1],cols[2])]


Do you know what is happening? Else, is there a more efficient solution to my problem?







python pandas for-loop list-comprehension






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 8 at 19:19









Juan C

19311




19311








  • 2




    Your last column is shorter than the others. zip stops when the shorter list ends. BTW: you should really consider extracting the expression that takes the value into a function: first_not_nan = lambda vals: next(x for x in vals if not math.isnan(x)) then result = list(map(first_not_nan, zip(A,B,C,D))).
    – Bakuriu
    Nov 8 at 19:25












  • Thanks Bakuriu! Could you explain me a little further your approach? I'm not really used to lambda expressions outside the apply function when trying to do an operation in every row of a Series. When I used both commands it got me a list of just 148 values. Maybe it stopped when it found a row consisting of only nan ? How could I fill it with a nan in that case? Thanks
    – Juan C
    Nov 8 at 19:35














  • 2




    Your last column is shorter than the others. zip stops when the shorter list ends. BTW: you should really consider extracting the expression that takes the value into a function: first_not_nan = lambda vals: next(x for x in vals if not math.isnan(x)) then result = list(map(first_not_nan, zip(A,B,C,D))).
    – Bakuriu
    Nov 8 at 19:25












  • Thanks Bakuriu! Could you explain me a little further your approach? I'm not really used to lambda expressions outside the apply function when trying to do an operation in every row of a Series. When I used both commands it got me a list of just 148 values. Maybe it stopped when it found a row consisting of only nan ? How could I fill it with a nan in that case? Thanks
    – Juan C
    Nov 8 at 19:35








2




2




Your last column is shorter than the others. zip stops when the shorter list ends. BTW: you should really consider extracting the expression that takes the value into a function: first_not_nan = lambda vals: next(x for x in vals if not math.isnan(x)) then result = list(map(first_not_nan, zip(A,B,C,D))).
– Bakuriu
Nov 8 at 19:25






Your last column is shorter than the others. zip stops when the shorter list ends. BTW: you should really consider extracting the expression that takes the value into a function: first_not_nan = lambda vals: next(x for x in vals if not math.isnan(x)) then result = list(map(first_not_nan, zip(A,B,C,D))).
– Bakuriu
Nov 8 at 19:25














Thanks Bakuriu! Could you explain me a little further your approach? I'm not really used to lambda expressions outside the apply function when trying to do an operation in every row of a Series. When I used both commands it got me a list of just 148 values. Maybe it stopped when it found a row consisting of only nan ? How could I fill it with a nan in that case? Thanks
– Juan C
Nov 8 at 19:35




Thanks Bakuriu! Could you explain me a little further your approach? I'm not really used to lambda expressions outside the apply function when trying to do an operation in every row of a Series. When I used both commands it got me a list of just 148 values. Maybe it stopped when it found a row consisting of only nan ? How could I fill it with a nan in that case? Thanks
– Juan C
Nov 8 at 19:35












2 Answers
2






active

oldest

votes

















up vote
2
down vote



accepted










You can use bfill(axis=1) and select the first col.



df.bfill(axis=1).iloc[:,0]

0 100.0
1 40.0
2 90.0
3 230.0
Name: prom_lect4b_rbd, dtype: float64

## For list
df.bfill(axis=1).iloc[:,0].tolist()
['100', '40', 90, '230']





share|improve this answer



















  • 1




    Thank you, worked like a charm! Pythonic and simple, way less convoluted than my solution.
    – Juan C
    Nov 8 at 19:39










  • @JuanC Happy to help. :)
    – Abhi
    Nov 8 at 19:42


















up vote
0
down vote













Use first_valid_index():



df.apply(lambda x: x[x.first_valid_index()], axis=1)


Yields:



0    100.0
1 40.0
2 90.0
3 230.0
dtype: float64





share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53214723%2fis-there-a-limit-for-zip-elements-in-loops-in-python%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    2
    down vote



    accepted










    You can use bfill(axis=1) and select the first col.



    df.bfill(axis=1).iloc[:,0]

    0 100.0
    1 40.0
    2 90.0
    3 230.0
    Name: prom_lect4b_rbd, dtype: float64

    ## For list
    df.bfill(axis=1).iloc[:,0].tolist()
    ['100', '40', 90, '230']





    share|improve this answer



















    • 1




      Thank you, worked like a charm! Pythonic and simple, way less convoluted than my solution.
      – Juan C
      Nov 8 at 19:39










    • @JuanC Happy to help. :)
      – Abhi
      Nov 8 at 19:42















    up vote
    2
    down vote



    accepted










    You can use bfill(axis=1) and select the first col.



    df.bfill(axis=1).iloc[:,0]

    0 100.0
    1 40.0
    2 90.0
    3 230.0
    Name: prom_lect4b_rbd, dtype: float64

    ## For list
    df.bfill(axis=1).iloc[:,0].tolist()
    ['100', '40', 90, '230']





    share|improve this answer



















    • 1




      Thank you, worked like a charm! Pythonic and simple, way less convoluted than my solution.
      – Juan C
      Nov 8 at 19:39










    • @JuanC Happy to help. :)
      – Abhi
      Nov 8 at 19:42













    up vote
    2
    down vote



    accepted







    up vote
    2
    down vote



    accepted






    You can use bfill(axis=1) and select the first col.



    df.bfill(axis=1).iloc[:,0]

    0 100.0
    1 40.0
    2 90.0
    3 230.0
    Name: prom_lect4b_rbd, dtype: float64

    ## For list
    df.bfill(axis=1).iloc[:,0].tolist()
    ['100', '40', 90, '230']





    share|improve this answer














    You can use bfill(axis=1) and select the first col.



    df.bfill(axis=1).iloc[:,0]

    0 100.0
    1 40.0
    2 90.0
    3 230.0
    Name: prom_lect4b_rbd, dtype: float64

    ## For list
    df.bfill(axis=1).iloc[:,0].tolist()
    ['100', '40', 90, '230']






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 8 at 19:42

























    answered Nov 8 at 19:31









    Abhi

    2,086319




    2,086319








    • 1




      Thank you, worked like a charm! Pythonic and simple, way less convoluted than my solution.
      – Juan C
      Nov 8 at 19:39










    • @JuanC Happy to help. :)
      – Abhi
      Nov 8 at 19:42














    • 1




      Thank you, worked like a charm! Pythonic and simple, way less convoluted than my solution.
      – Juan C
      Nov 8 at 19:39










    • @JuanC Happy to help. :)
      – Abhi
      Nov 8 at 19:42








    1




    1




    Thank you, worked like a charm! Pythonic and simple, way less convoluted than my solution.
    – Juan C
    Nov 8 at 19:39




    Thank you, worked like a charm! Pythonic and simple, way less convoluted than my solution.
    – Juan C
    Nov 8 at 19:39












    @JuanC Happy to help. :)
    – Abhi
    Nov 8 at 19:42




    @JuanC Happy to help. :)
    – Abhi
    Nov 8 at 19:42












    up vote
    0
    down vote













    Use first_valid_index():



    df.apply(lambda x: x[x.first_valid_index()], axis=1)


    Yields:



    0    100.0
    1 40.0
    2 90.0
    3 230.0
    dtype: float64





    share|improve this answer

























      up vote
      0
      down vote













      Use first_valid_index():



      df.apply(lambda x: x[x.first_valid_index()], axis=1)


      Yields:



      0    100.0
      1 40.0
      2 90.0
      3 230.0
      dtype: float64





      share|improve this answer























        up vote
        0
        down vote










        up vote
        0
        down vote









        Use first_valid_index():



        df.apply(lambda x: x[x.first_valid_index()], axis=1)


        Yields:



        0    100.0
        1 40.0
        2 90.0
        3 230.0
        dtype: float64





        share|improve this answer












        Use first_valid_index():



        df.apply(lambda x: x[x.first_valid_index()], axis=1)


        Yields:



        0    100.0
        1 40.0
        2 90.0
        3 230.0
        dtype: float64






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 8 at 19:29









        rahlf23

        4,3501629




        4,3501629






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53214723%2fis-there-a-limit-for-zip-elements-in-loops-in-python%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Schultheiß

            Verwaltungsgliederung Dänemarks

            Liste der Kulturdenkmale in Wilsdruff