Как вставить символ в список, основываясь на последовательном появлении двух элементов из другого списка?питон - PullRequest
0 голосов
/ 23 мая 2018

У меня есть DataFrame с большим количеством строк и функцией, которая вставляет символ в строку в соответствии с условием.Проблема в том, что мой код каким-то образом неправильно видит входную строку s.

Список s состоит из элементов из двух списков: (1) список участников (2) список не членов.Моя цель - вставить число «1» в s, когда за любым «членом» следуют любые два последовательных «не члена».Максимум один '1' должен быть добавлен к s.Это код.

import pandas as pd
members = ['AA', 'BBB', 'CC', 'DDDD']
non_members = ['EEEE', 'FF', 'GGG', 'HHHHH', 'III', 'JJ']
s = ['AA', 'EEEE', 'GGG', 'FF']

Таким образом, я пытаюсь добиться результата для s, чтобы получить следующий вывод:

['AA', '1', 'EEEE', 'GGG', 'FF']

Это мой код:

df = pd.DataFrame(s, columns =['string'])
d = df['string']

def func(row):
    out = ""
    look = 2
    for i in range(len(row)-look):
        out += row[i]
        if (row[i] in members) & \
           (row[i+1] in non_members) & \
           (row[i+2] in non_members):
            out += '1' + row[i+1:]
            break
    return out

e = d.apply(func)
print(e)

Это дает следующий результат:

0      
1    EE
2     G
3      

Но я надеюсь получить следующее:

['AA', '1', 'EEEE', 'GGG', 'FF']

Есть предложения, как решить эту проблему?

Этот вопрос связан с этим: Как добавить символ в список, если два элемента из другого списка появляются последовательно?Python

Ответы [ 3 ]

0 голосов
/ 23 мая 2018

@ ALollz код выглядит чище, потому что они используют маску и исин, но да, определенно идея сдвига.

import pandas as pd

import sys 

def fun(row):
    members = ['AA', 'BBB', 'CC', 'DDDD']
    non_members = ['EEEE', 'FF', 'GGG', 'HHHHH', 'III', 'JJ']
    try:
        if (row["string"] in members):
            if(row["next"] in non_members):
                if(row["nextnext"] in non_members):
                    return(1)
        return(0)
    except:
        e = sys.exc_info()[0]
        print(e)
        print("!")
        return(0)
    return(0)

def insert_row(idx, df, df_insert):
    dfA = df.iloc[:idx, ]
    dfB = df.iloc[idx:, ]
    df = dfA.append(df_insert).append(dfB).reset_index(drop = True)
    return df

def primary(d):
    df = d.copy()
    a = d.shift(-1)
    b = d.shift(-2)
    df['next'] = a
    df['nextnext'] = b
    e = df.apply(fun,axis=1)
    x = 0
    while( x<len(e) and e[x]==0 ):
        x+=1
    if(x!=len(e)):
        d = insert_row(x+1,d,pd.DataFrame(["1"], columns=["string"]))
    return(d)

s = ['AA', 'EEEE', 'GGG', 'FF']

df = pd.DataFrame(s, columns =['string'])
print(primary(df))
0 голосов
/ 23 мая 2018

Мне нравится ответ ALollz, но я предпочитаю более визуальный подход.Вот пример, в котором требуется две вставки.

import pandas as pd
import numpy as np
members = ['AA', 'BBB', 'CC', 'DDDD']
non_members = ['EEEE', 'FF', 'GGG', 'HHHHH', 'III', 'JJ']
s = ['AA', 'EEEE', 'GGG', 'CC', 'III', 'JJ']
ser = pd.Series(s)
# view the multiple "frames" from the list in a dataframe
df = pd.DataFrame([ser, ser, ser.shift(-1), ser.shift(-2)], 
index=["orig","s", "s+1", "s+2"]).T

   orig     s   s+1  s+2
0    AA    AA  EEEE  GGG
1  EEEE  EEEE   GGG   CC
2   GGG   GGG    CC  III
3    CC    CC   III   JJ
4   III   III    JJ  NaN
5    JJ    JJ   NaN  NaN

Подобно маске, создайте столбец, показывающий, выполняются ли условия.

df["s"] = df["s"].isin(members)
df["s+1"] = df["s+1"].isin(non_members)
df["s+2"] = df["s+2"].isin(non_members)
df["fulfilled"] = df.all(axis=1)

   orig      s    s+1    s+2  fulfilled
0    AA   True   True   True       True
1  EEEE  False   True  False      False
2   GGG  False  False   True      False
3    CC   True   True   True       True
4   III  False   True  False      False
5    JJ  False  False  False      False

получите индекс "1"позиции для вставки в окончательный список s_out.Это просто индекс оригинала плюс индекс только в «истинных» позициях

index = df.loc[df.fulfilled].index
df.loc[index, "index in s_out"] = index + np.arange(1, len(index) + 1)

   orig      s    s+1    s+2  fulfilled  index in s_out
0    AA   True   True   True       True             1.0
1  EEEE  False   True  False      False             NaN
2   GGG  False  False   True      False             NaN
3    CC   True   True   True       True             5.0
4   III  False   True  False      False             NaN
5    JJ  False  False  False      False             NaN

Вставьте «1» в список s_out в требуемых позициях.

s_out = s.copy()
for i in df["index in s_out"].dropna().astype(int):
    s_out.insert(i, "1")
s_out

['AA', '1', 'EEEE', 'GGG', 'CC', '1', 'III', 'JJ']
0 голосов
/ 23 мая 2018

Вы можете использовать сдвиг, чтобы выяснить, где выполняется это условие.

mask = ((df['string'].isin(members)) 
         & (df['string'].shift(-1).isin(non_members)) 
         & (df['string'].shift(-2).isin(non_members)))

Одним из способов вставки в строки между ними может быть что-то подобное.

import numpy as np
df.set_index(df.index*2, inplace=True)

indices = mask[mask==True].index.values+1

df_add = pd.DataFrame(data=np.repeat(1, len(indices)), index=indices, columns=['string'])

pd.concat([df, df_add]).sort_index()
  string
0     AA
1      1
2   EEEE
4    GGG
6     FF
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...