Преобразование кадра данных на основе статуса идентификатора - PullRequest
2 голосов
/ 10 марта 2020

У меня есть следующий фрейм данных

    USER_ID MONTH       STATUS_ID
0   23026   2019-09-01  2
1   23026   2019-10-01  2
2   23026   2019-11-01  2
3   23026   2019-12-01  2
4   23027   2019-09-01  2
... ... ... ...
123 16546   2018-10-01  2
124 16622   2018-09-01  1
125 16622   2018-10-01  1
126 16622   2018-11-01  1
127 16622   2018-12-01  1

У всех пользователей должно быть 4 строки (4 месяца), но период может быть другим (01.02.2018 -01.05.2018 или 01.02.2019 - 01.05.2019 .. .)

, и я хотел бы преобразовать вот так

    USER_ID MONTH_1 MONTH_2 MONTH_3 MONTH_4
0   23026   2       2       2       2
1   23027   2       2       2       2
... ... ... ...
123 16546   2       2       1       1
124 16622   1       1       1       1

и последнее, что мне нужно преобразовать - это STATUS ID

    USER_ID ID
0   23026   2    
1   23027   2    
... ... ... ...
123 16546   2
124 16622   1

Это своего рода логической операции между идентификаторами в разные месяцы. Есть идеи, как это преобразовать? Или это может быть решено более эффективно?

Ответы [ 3 ]

2 голосов
/ 10 марта 2020

Я думаю, что возможным решением является создание нового столбца по счетам с GroupBy.cumcount и переход к DataFrame.pivot:

print (df)
     USER_ID       MONTH  STATUS_ID
0      23026  2019-09-01          2
1      23026  2019-10-01          2
2      23026  2019-11-01          2
3      23026  2019-12-01          2
123    16546  2018-09-01          2
123    16546  2018-10-01          2
123    16546  2018-11-01          1
123    16546  2018-12-01          1
124    16622  2018-09-01          1
125    16622  2018-10-01          1
126    16622  2018-11-01          1
127    16622  2018-12-01          1

df['MONTH1'] = 'MONTH_' + df.groupby('USER_ID').cumcount().add(1).astype(str)
df = df.pivot('USER_ID','MONTH1','STATUS_ID')
print (df)
MONTH1   MONTH_1  MONTH_2  MONTH_3  MONTH_4
USER_ID                                    
16546          2        2        1        1
16622          1        1        1        1
23026          2        2        2        2

Затем сравнение по 1 на DataFrame.eq и проверьте, если хотя бы один True на строки, на DataFrame.any, последний map и преобразуйте в DataFrame:

df1 = df1.eq(1).any(axis=1).map({True:1, False:2}).reset_index(name='ID')
print (df1)
   USER_ID  ID
0    16546   1
1    16622   1
2    23026   2

Деталь :

print (df1.eq(1))
MONTH1   MONTH_1  MONTH_2  MONTH_3  MONTH_4
USER_ID                                    
16546      False    False     True     True
16622       True     True     True     True
23026      False    False    False    False
0 голосов
/ 10 марта 2020

Ваш вопрос неясен относительно формата первого столбца вашего окончательного вывода.

Настройте эти два сценария по мере необходимости:

Требуется, чтобы каждый идентификатор имел всегда 4 линий. Также первый пользователь / последний пользователь может быть пропущен.

#!/usr/bin/env python3                                                                                                                  

import csv                                                                                           

prev_id = 0                                                                                          
sc = 0                                                                                               
buf = [0, 0, 0, 0]                                                                                   

with open("test.csv") as f:                                                                          
    data = csv.reader(f, delimiter=' ', skipinitialspace=True)                                       
    for row in data:                                                                                 
        if sc == 4:                                                                                  
            print(int(row[0]) - 4, prev_id, buf[0], buf[1], buf[2], buf[3])                          
            sc = 0                                                                                   
        else:                                                                                        
            prev_id = row[1]                                                                         
            buf[sc] = row[3]                                                                         
            sc += 1                           
#!/usr/bin/env python3                                                                                  
import csv                                                                                              

prev_id = 0                                                                                             
prev_stat_max = 0                                                                                       
counter = 0                                                                                             

with open('test.csv') as f:                                                                                                             
    data = csv.reader(f, delimiter=' ', skipinitialspace=True)                                          
    length = sum(1 for row in data)                                                                     

with open('test.csv') as f:                                                                             
    data = csv.reader(f, delimiter=' ', skipinitialspace=True)                                          
    for row in data:                                                                                    
        if prev_id == row[1]:                                                                           
            if row[3] > prev_stat_max:                                                                  
                priv_stat_max = row[3]                                                                  
        else:                                                                                           
            print(counter, prev_id, prev_stat_max)                                                      
        prev_id = row[1]                                                                                
        prev_stat_max = row[3]                                                                          
        counter += 1                                                                                    
        if counter == length:                                                                           
            print(counter, prev_id, prev_stat_max)
0 голосов
/ 10 марта 2020
import pandas as pd

df = pd.DataFrame(
    [
        {"USER_ID": 23026, "MONTH": "2019-09-01", "STATUS_ID": 2},
        {"USER_ID": 23026, "MONTH": "2019-10-01", "STATUS_ID": 2},
        {"USER_ID": 23026, "MONTH": "2019-11-01", "STATUS_ID": 2},
        {"USER_ID": 16622, "MONTH": "2019-09-01", "STATUS_ID": 1},
        {"USER_ID": 16622, "MONTH": "2019-10-01", "STATUS_ID": 1},
        {"USER_ID": 16622, "MONTH": "2019-11-01", "STATUS_ID": 1},
    ]
)

pivoted = df.pivot(index="USER_ID", columns="MONTH", values="STATUS_ID")
# Sort column names
pivoted = pivoted.reindex(sorted(pivoted.columns), axis=1)
pivoted.columns = ["MONTH_" + str(x) for x in range(1, len(pivoted.columns) + 1)]
print(pivoted)
# if you want USER_ID as a regular column use:
# pivoted = pivoted.reset_index(col_fill="USER_ID")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...