Repeat rows based on item count for each row and assign values for repeated rows

Viewed 138

I have a df with the item and it is available in different rooms

  Item     Room1  Room2  Room3  Room4
  Ball      1       1     1        0
  Bat       1       1     1        1
  Wicket    1       1     1        0

Now I want to repeat the rows based on item counts on different Rooms. For example for Item - Ball there are three 1's in Room1, Room2, Room3 so need to repeat 3 rows with assigning 0 in each row only for Room1, Room2, Room3 columns, and Room4 is not considered for Item Ball and it can be 0's for all Ball item rows. There are 300 columns with different room names, for example Room1,room2,room3,room4,BlockArea1,Block2 etc.Below is the expected output

  Item     Room1  Room2  Room3  Room4
  Ball      1       1     1        0
  Ball      1       0     1        0
  Ball      1       1     0        0 
  Bat       1       1     1        1
  Bat       1       1     1        0
  Bat       1       1     0        1
  Bat       1       0     1        1
  Wicket    1       1     1        0
  Wicket    1       0     1        0
  Wicket    1       1     0        0

Any help would be appreciated

1 Answers

To have a more interesting example, with a source row containing 0 somewhere else than in the last column, I created df as:

     Item  Room1  Room2  Room3  Room4
0    Ball      1      1      1      0
1     Bat      1      1      1      1
2  Wicket      1      1      1      0
3    Xxxx      0      1      1      1

The first step is to define a function to process each row:

def rowProc(row):
    n = 0
    res = []
    for idx, val in row[row > 0].items():
        outRow = row.copy()
        if n > 0:
            outRow[idx] = 0
        res.append(outRow)
        n += 1
    return pd.DataFrame(res)

An important project detail is that the source row comes here from a bit "changed" DataFrame, namely Item column will be set as the index. So the only processed columns are "further" (Room...) columns.

For the current row it generates a DataFrame containing:

  • as many rows as how many ones contains the source row,
  • the first output row is an exact copy of the source row (like in your expected result),
  • further rows have consecutive ones set to 0.

Then run:

result = pd.concat(df.set_index('Item').apply(rowProc, axis=1).tolist())
result.index.name = 'Item'
result.reset_index(inplace=True)

The result is:

      Item  Room1  Room2  Room3  Room4
0     Ball      1      1      1      0
1     Ball      1      0      1      0
2     Ball      1      1      0      0
3      Bat      1      1      1      1
4      Bat      1      0      1      1
5      Bat      1      1      0      1
6      Bat      1      1      1      0
7   Wicket      1      1      1      0
8   Wicket      1      0      1      0
9   Wicket      1      1      0      0
10    Xxxx      0      1      1      1
11    Xxxx      0      1      0      1
12    Xxxx      0      1      1      0
Related