Pandas Заполнение недостающих строк на основе определенного списка - PullRequest
0 голосов
/ 09 июля 2020

Original DF имеет значения, которые вычисляются из таблицы.

Может отсутствовать type для нескольких идентификаторов. Однако цель явно перечисляется, если установлен флаг exists. В противном случае следует добавить строку type с no в столбец exists. В этом примере подходит

id = 1. Если я фильтрую только по id = 2 и запускаю следующий код, он возвращает c. что я могу затем append.

aa = set(type)
bb = set(b['type'].to_list())
list(aa - bb)

Однако, как вы можете сказать, это невозможно при применении ко всем идентификаторам.

Мне нужна была помощь, чтобы код можно было применить для все идентификаторы.

Это возвращает тип, который не

type = [a, b, c]

Original
id      type    flag    
1       a       y        
1       b       y
1       c       y
2       a       y      
2       b       y
3       b       y     

Goal
id      type    flag    exists 
1       a       y       yes        
1       b       y       yes       
1       c       y       yes       
2       a       y       yes            
2       b       y       yes   
2       c       y       no     
3       a       y       yes        
3       b       y       no 
3       b       y       no    

Надеюсь, что есть лучший способ справиться с этим.

1 Ответ

1 голос
/ 09 июля 2020

Ключ в том, чтобы сгенерировать декартово произведение между набором идентификаторов и набором типов. Я использовал это декартово произведение аксиома

data = '''id ,     type ,   flag    
1   ,    a    ,   y        
1    ,   b    ,   y
1    ,   c    ,   y
2   ,    a    ,   y      
2    ,   b    ,   y
3     ,  b     ,  y     '''
da = [[i.strip() for i in l.split(",")] for l in data.split("\n")]
df = pd.DataFrame(da[1:], columns=da[0])
# generate cartesian product https://apassionatechie.wordpress.com/2018/01/15/pandas-equivalent-of-sql-cross-join-cartesian-product/
cp = pd.DataFrame(["a","b","c"], columns=["type"])\
        .assign(foo=1)\
        .merge(pd.DataFrame(df["id"].unique(), columns=["id"]).assign(foo=1)).drop('foo',1)
df = cp.merge(df, how="outer", on=["id","type"])
df["exists"] = ~df["flag"].isnull()
df.fillna(method="ffill")

вывод

    type    id  flag    exists
0   a   1   y   True
1   a   2   y   True
2   a   3   y   False
3   b   1   y   True
4   b   2   y   True
5   b   3   y   True
6   c   1   y   True
7   c   2   y   False
8   c   3   y   False

...