Панды, объединяющие информацию из нескольких столбцов, где значение зависит от значений в одной строке - PullRequest
4 голосов
/ 26 сентября 2019

Я пытаюсь сжать информацию из нескольких столбцов в один.Во фрейме данных есть столбцы «step», «tx» и «rx».За ними следуют столбцы, которые показывают накопленное значение, передаваемое между сторонами, так что «A_to_B» и т. Д. Но я хочу сжать информацию в один столбец, который показывает соответствующее накопленное значение на данном шаге для данной передачи.Таким образом, значение в объединенном столбце зависит от того, какие стороны участвуют в передаче, т.е.значение зависит от других значений в той же строке.Приведенный ниже код делает это:

u = pd.DataFrame()
u["step"] = pd.Series([1,2,3,4,5,6])
u["tx"] = pd.Series(["A","A","A","A","A","B"])
u["rx"] = pd.Series(["B","C","B","C","C","A"])
u["A_to_B"] = pd.Series([15,15,30,30,30,30])
u["A_to_C"] = pd.Series([0,20,20,40,50,50])
u["B_to_A"] = pd.Series([0,0,0,0,0,100])

print(u)

def compact(x):
  rx = x["rx"]
  tx = x["tx"]
  x["combo"] = x[tx + "_to_" + rx]
  return x

u = u.apply(lambda x: compact(x), axis=1)

print(u)

Это дает следующее:

   step tx rx  A_to_B  A_to_C  B_to_A
0     1  A  B      15       0       0
1     2  A  C      15      20       0
2     3  A  B      30      20       0
3     4  A  C      30      40       0
4     5  A  C      30      50       0
5     6  B  A      30      50     100
   step tx rx  A_to_B  A_to_C  B_to_A  combo
0     1  A  B      15       0       0     15
1     2  A  C      15      20       0     20
2     3  A  B      30      20       0     30
3     4  A  C      30      40       0     40
4     5  A  C      30      50       0     50
5     6  B  A      30      50     100    100

Проблема в том, что это очень медленно работает на большом количестве строк,Есть ли более эффективный способ сделать эту операцию?

Ответы [ 2 ]

2 голосов
/ 26 сентября 2019

Используйте df.lookup здесь:

s=u['tx']+'_to_'+u['rx']
u['combo']=u.lookup(s.index,s)

То же самое, используя функцию (если вам нужно):

def compact(x):
    s=x['tx']+'_to_'+x['rx']
    return x.assign(combo=x.lookup(s.index,s))
compact(u)

   step tx rx  A_to_B  A_to_C  B_to_A  combo
0     1  A  B      15       0       0     15
1     2  A  C      15      20       0     20
2     3  A  B      30      20       0     30
3     4  A  C      30      40       0     40
4     5  A  C      30      50       0     50
5     6  B  A      30      50     100    100

Производительность:

u = pd.concat([u]*2000,ignore_index=True)
%%timeit
s=u['tx']+'_to_'+u['rx']
u.lookup(s.index,s)
#16.6 ms ± 754 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit
u.assign(lookup=u['tx'].str.cat(u['rx'], sep='_to_')).apply(lambda x: x[x['lookup']],1)
#613 ms ± 79.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
#lookup is faster than apply
1 голос
/ 26 сентября 2019

Вам необходимо использовать assign и создать столбец поиска.Затем с apply значениями выборки.

u['combo'] = u.assign(lookup=u['tx'].str.cat(u['rx'], sep='_to_')).apply(lambda x: x[x['lookup']],1)

Вывод:

   step tx rx  A_to_B  A_to_C  B_to_A  combo
0     1  A  B      15       0       0     15
1     2  A  C      15      20       0     20
2     3  A  B      30      20       0     30
3     4  A  C      30      40       0     40
4     5  A  C      30      50       0     50
5     6  B  A      30      50     100    100
...