简体   繁体   中英

more effective way to iterate

I want to return the row items whose position dropped compared to previous columns position. IS there better/more simpler way to do this? I have dataframe where there are items in order and the order can change in next column (week):

s1 = pd.Series(["item1", "item2", "item3"])
s2 = pd.Series(["item2", "item1", "item3"])
s3 = pd.Series(["item3","item2", "item1"])
data = pd.DataFrame({"week1":s1, "week2":s2, "week3":s3})

# I did it like this

counter1 = 0 # iterate all columns
idxfirst = 0 # manually index
idxsecond = 0 # manually index
numberofcolumns = (len(data.columns))-1

for i in range(numberofcolumns):
    idxfirst = 0
    for i in data.iloc[:,counter1]:
        idxsecond = 0
        for j in data.iloc[:,(counter1+1)]:
            if i == j and idxfirst < idxsecond:
                print(i)
        
            idxsecond += 1
        
        idxfirst +=1
        
    counter1 +=1
prints:
item1 # because position dropped from 1 to 2 in second week
item2 # because position dropped from 1 to 2 in second week
item1 # because position dropped from 2 to 3 in third week

You can simplify your code with enumerate() :

s1 = pd.Series(["item1", "item2", "item3"])
s2 = pd.Series(["item2", "item1", "item3"])
s3 = pd.Series(["item3","item2", "item1"])
data = pd.DataFrame({"week1":s1, "week2":s2, "week3":s3})

numberofcolumns = (len(data.columns))-1

for counter1,i in enumerate(range(numberofcolumns)):
    for idxfirst,i in enumerate(data.iloc[:,counter]):
        for idxsecond,j in enumerate(data.iloc[:,(counter+1)]):
            if i == j and idxfirst < idxsecond:
                print(i)

Here's a way to do it in a fully vectorized manner, by 'melting' the dataframe, joining it to itself, and then looking for rows that meet three conditions:

  • The item from the first week is identical to the item on the following week.
  • Week1 + 1 == week2
  • The index of the first item is smaller than the index of the second item.

    df = data.reset_index().melt(id_vars="index")
    df["week"] = df.variable.str.replace("week", "").astype(int)
    df = df[["index", "value", "week"]]
    df = pd.merge(df.assign(dummy = 1), df.assign(dummy=1), on = "dummy") 
    df[(df.value_x == df.value_y) & (df.week_x + 1 == df.week_y) & (df.index_x < df.index_y)]["value_x"]

Output:

4     item1
34    item2
44    item1
Name: value_x, dtype: object

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM