У меня есть датафрейм, как показано ниже

     Token          Label  StartID  EndID  
0   Germany         Country   0      2     
1   Berlin          Capital   6      9       
2   Frankfurt       City      15     18        
3   four   million  Number    21     24        
4   Sweden          Country   26     27       
5   United Kingdom  Country   32     34     
6   ten million     Number    40     45
7   London          Capital   50     55

Я пытаюсь получить строку на основе определенного условия, то есть связать метку Number с ближайшим capital т. Е. Berlin

3   four   million  Number    21     24   - > 1   Berlin          Capital   6      9

Или что-то вроде:

df[row3] -> df [row1]

Псевдо логика

Сначала проверьте строки с label: Number затем (предполагается, что город всегда «на 2 строки» выше или ниже) и имеет label: Capital. Но label: «прописной» loc всегда после label: Country

Что я сделал до сих пор,

columnsName =['Token', 'Label', 'StartID', 'EndID']
df = pd.read_csv('resources/testcsv.csv', index_col= 0, skip_blank_lines=True, header=0)
print(df)

key_number = 'Number'
df_with_number = (df[df['Label'].str.lower().str.contains(r"\b{}\b".format(key_number), regex=True, case=False)])
print(df_with_number)

key_capital = 'Capital'
df_with_capitals = (df[df['Label'].str.lower().str.contains(r"\b{}\b".format(key_capital), regex=True, case=False)])
print(df_with_capitals)

key_country = 'Country'
df_with_country = (df[df[1].str.lower().str.contains(r"\b{}\b".format(key_country), regex=True, case=False)])
print(df_with_country)

Логика состоит в том, чтобы сравнить индексы, а затем сделать возможным отношения

То есть

df[row3] -> [ df [row1], df[row7]]
0
Betafish 29 Апр 2020 в 17:38

2 ответа

Лучший ответ

Вы можете использовать merge_asof с параметром direction=nearest, например:

df_nb_cap = pd.merge_asof(df_with_number.reset_index(), 
                          df_with_capitals.reset_index(), 
                          on='index', 
                          suffixes=('_nb', '_cap'), direction='nearest')
print (df_nb_cap)
   index      Token_nb Label_nb  StartID_nb  EndID_nb Token_cap Label_cap  \
0      3  four_million   Number          21        24    Berlin   Capital   
1      6   ten_million   Number          40        45    London   Capital   

   StartID_cap  EndID_cap  
0            6          9  
1           50         55 
1
Ben.T 29 Апр 2020 в 14:57
# adjusted sample data
s = """Token,Label,StartID,EndID  
Germany,Country,0,2     
Berlin,Capital,6,9       
Frankfurt,City,15,18        
four million,Number,21,24        
Sweden,Country,26,27       
United Kingdom,Country,32,34
ten million,Number,40,45
London,Capital,50,55
ten million,Number,40,45
ten million,Number,40,45"""
df = pd.read_csv(StringIO(s))

# create a mask for number where capital is 2 above or below
# and where country is three above number or one below number
mask = (df['Label'] == 'Number') & (((df['Label'].shift(2) == 'Capital') | 
                                     (df['Label'].shift(-2) == 'Capital')) & 
                                    (df['Label'].shift(3) == 'Country') | 
                                    (df['Label'].shift(-1) == 'Country'))

# create a mask for capital where number is 2 above or below
# and where country is one above capital
mask2 = (df['Label'] == 'Capital') & (((df['Label'].shift(2) == 'Number') | 
                                       (df['Label'].shift(-2) == 'Number')) & 
                                      (df['Label'].shift(1) == 'Country'))

# hstack your two masks and create a frame
new_df = pd.DataFrame(np.hstack([df[mask].to_numpy(), df[mask2].to_numpy()]))
print(new_df)

              0       1   2   3       4        5  6  7
0  four million  Number  21  24  Berlin  Capital  6  9
1
Yo_Chris 29 Апр 2020 в 15:15