Создание списка значений в DataFrame в зависимости от значений в другом столбце - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть кадр данных панд, как показано здесь. В этом кадре есть еще много столбцов, которые не важны для задачи.

id    pos      value       sente
1     a         I           21
2     b         have        21
3     b         a           21
4     a         cat         21
5     d         !           21
1     a         My          22
2     a         cat         22
3     b         is          22
4     a         cute        22
5     d         .           22

Я хотел бы составить список из определенных столбцов, чтобы первое предложение (sente = 21) и все остальные выглядели примерно так. Это означает, что каждое предложение имеет уникальную запись для себя.

`[('I', 'a', '1'), ..., ('!','d','5')]`

У меня уже есть функция сделать это для одного предложения, но я не могу понять, как это сделать для всех предложений (предложений, имеющих одинаковое значение sente) в кадре.

`class SentenceGetter(object):
  def __init__(self, data):
    self.n_sent = 1
    self.data = data
    self.empty = False
  def get_next(self):
    for t in self.data:
        try:
            s = self.data[(self.data["sente"] == 21)]
            self.n_sent += 1
            return 
              s["id"].values.tolist(),   
              s["pos"].values.tolist(),
              s["value"].values.tolist() 
        except:
            self.empty = True
            return None,None,None

foo = SentenceGetter(df)
sent, pos, token = foo.get_next()
in = zip(token, pos, sent)

`

Поскольку мой фрейм очень большой, нет возможности использовать такие конструкции:

df.loc[((df["sente"] == df["sente"].shift(-1)) & (df["sente"] == df["sente"].shift(+1))), ["pos","value","id"]]

Есть идеи?

Ответы [ 3 ]

0 голосов
/ 29 апреля 2018

Вы также можете использовать функции groupby и apply.

Метод 1: Дает фрейм данных

(df
 .groupby('sente')
 .apply(lambda df: list(tuple(x) for x in df[['value','pos','id']].values))
 .reset_index()
 .rename(columns={0: 'values'}))

   sente                                             values
0     21  [(I, a, 1), (have, b, 2), (a, b, 3), (cat, a, ...
1     22  [(My, a, 1), (cat, a, 2), (is, b, 3), (cute, a...

Метод 2: Это дает словарь

(df
 .groupby('sente')
 .apply(lambda df: list(tuple(x) for x in df[['value','pos','id']].values))
 .reset_index()
 .set_index('sente')[0].to_dict())
0 голосов
/ 29 апреля 2018

По сути то же самое, что и ответ @ YOLO

def f(df):
    s = df[['value','pos','id']].apply(tuple, axis=1)
    return s.tolist()
g = df.groupby('sente')
q = g.apply(f)

>>> type(q)
<class 'pandas.core.series.Series'>
>>> q[21]
[('I', 'a', 1), ('have', 'b', 2), ('a', 'b', 3), ('cat', 'a', 4), ('!', 'd', 5)]
>>> q[22]
[('My', 'a', 1), ('cat', 'a', 2), ('is', 'b', 3), ('cute', 'a', 4), ('.', 'd', 5)]

>>> q.tolist()
[[('I', 'a', 1), ('have', 'b', 2), ('a', 'b', 3), ('cat', 'a', 4), ('!', 'd', 5)], [('My', 'a', 1), ('cat', 'a', 2), ('is', 'b', 3), ('cute', 'a', 4), ('.', 'd', 5)]]
>>>
>>> q.to_dict()
{21: [('I', 'a', 1), ('have', 'b', 2), ('a', 'b', 3), ('cat', 'a', 4), ('!', 'd', 5)], 22: [('My', 'a', 1), ('cat', 'a', 2), ('is', 'b', 3), ('cute', 'a', 4), ('.', 'd', 5)]}
>>>
0 голосов
/ 29 апреля 2018

Если вы открыты для использования стандартной библиотеки, collections.defaultdict предлагает решение O (n):

from collections import defaultdict

d = defaultdict(list)

for _, num, *data in df[['sente', 'value', 'pos', 'id']].itertuples():
    d[num].append(data)

Результат:

defaultdict(list,
            {21: [('I', 'a', 1),
                  ('have', 'b', 2),
                  ('a', 'b', 3),
                  ('cat', 'a', 4),
                  ('!', 'd', 5)],
             22: [('My', 'a', 1),
                  ('cat', 'a', 2),
                  ('is', 'b', 3),
                  ('cute', 'a', 4),
                  ('.', 'd', 5)]})
...