Как заполнить фрейм данных Pandas этими данными csv? - PullRequest
0 голосов
/ 09 мая 2020

Хорошо, совсем недавно pandas, но нужно получить данные из этого https://www.kaggle.com/datasnaek/mbti-type csv в новый Pandas фрейм данных.

CSV структурирован следующим образом:

type                posts

intj "hello world ||| http://linkhere ||| blah blah |||"
entj "hello world ||| http://linkhere ||| blah blah |||"
entj "hello world ||| http://linkhere ||| blah blah |||"
estj "hello world ||| http://linkhere ||| blah blah |||"
intp "hello world ||| http://linkhere ||| blah blah |||"

Существует 16 типов (type1 - type16), которые повторяются для более чем 8000 записей, и каждый элемент в сообщениях представляет собой строку, которая, если разделение на ||| будет массивом из 50 строк.

Мне также нужно УДАЛИТЬ любую из этих 50 строк для каждого элемента сообщений, которые содержат «http»

Мне нужно:

target   type    post
1      intj    "hello world shdjd"
2      entp    "hello world fddf"
16     estj   "hello world dsd"
4      esfp    "hello world sfs"
1      intj    "hello world ddfd"

Где каждый тип (потому что в csv типы НЕ помечены как type1 - type16, но имеют другие имена) сопоставляется со своей целью (целое число от 1 до 16), и каждое сообщение, которое было разделено после каждого ||| из каждого posts элемент получает свою строку.

Я смотрел https://www.geeksforgeeks.org/split-a-text-column-into-two-columns-in-pandas-dataframe/ и аналогичные, но получаю очень странные результаты.

Как я могу создать этот новый фрейм данных?

EDIT : Хорошо, теперь у меня есть каждый элемент сообщений в виде массива, разделенного на ||| с:

mbtiData.posts.str.split('\|\|\|', expand=True)

, но не знаю, как вернуть их в фрейм данных.

Ответы [ 2 ]

1 голос
/ 09 мая 2020

Предположим, что ваш входной файл содержит:

type                posts

intj "hello world 1 ||| http://linkhere ||| blah blah 6 |||"
entj "hello world 2 ||| http://linkhere ||| blah blah 7 |||"
entj "hello world 3 ||| http://linkhere ||| blah blah 8 |||"
estj "hello world 4 ||| http://linkhere ||| blah blah 9 |||"
intp "hello world 5 ||| http://linkhere ||| blah blah 10 |||"

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

df = pd.read_csv('Input.csv', sep=r'\s+')

Затем определите функция фильтрации:

def myFilter(tbl):
    return pd.Series([x for x in tbl if len(x) > 0 and 'http' not in x], dtype='O')

которая:

  • фильтрует исходный список (таблицу строк) из пустых строк и строк, содержащих http ,
  • преобразует его в Series .

Явное dtype требуется спецификация 1.0 , чтобы заглушить DeprecationWarning , которое в противном случае происходит, если выходной ряд был пуст. Для ваших данных этого не происходит, но это может произойти, если в любой строке все сообщения были отфильтрованы.

Затем запустите:

result = df.set_index('type').posts.str.split(r' *[\|]{3} *').apply(myFilter)\
    .stack().reset_index(level=1, drop=True).reset_index(name='post')

Шаги:

  • Установить тип столбец в качестве индекса.
  • Разделить сообщения столбец на тройку «|», возможно, окруженный пробелами. На данный момент каждый результат разделения содержит простой Pythoni c список с пустой строкой в ​​конце и «http-строкой», если есть.
  • Apply myFilter чтобы отфильтровать ненужные строки. Результатом теперь является DataFrame со столбцами, названными последовательными целыми числами для каждого содержащегося сообщения.
  • stack () , чтобы преобразовать его в Series с MultiIndex:
    • верхний уровень - источник тип ,
    • второй уровень - имя столбца источника (индекс сообщения в исходной строке).
  • Отбросьте второй уровень индекса.
  • Преобразуйте единственный оставшийся уровень индекса в «обычный» столбец и переименуйте столбец, содержащий сообщения, в сообщение .

Результат для моих исходных данных:

   type           post
0  intj  hello world 1
1  intj    blah blah 6
2  entj  hello world 2
3  entj    blah blah 7
4  entj  hello world 3
5  entj    blah blah 8
6  estj  hello world 4
7  estj    blah blah 9
8  intp  hello world 5
9  intp   blah blah 10

Чтобы сгенерировать целевой столбец, вы должны:

  • определить определение сопоставления (например, словарь ), что-то вроде types = {'intj': 1, 'entj': 2, 'estj': 3, 'intp': 4} (включая все требуемые строки типов и соответствующие целевые значения),
  • вставить целевой столбец, вызывая result.insert(0, 'target', result.type.apply(lambda tp: types[tp]))

Теперь результат:

   target  type           post
0       1  intj  hello world 1
1       1  intj    blah blah 6
2       2  entj  hello world 2
3       2  entj    blah blah 7
4       2  entj  hello world 3
5       2  entj    blah blah 8
6       3  estj  hello world 4
7       3  estj    blah blah 9
8       4  intp  hello world 5
9       4  intp   blah blah 10

Конечно, вы можете назначить другие сопоставления типа «целевой».

0 голосов
/ 09 мая 2020

Может быть, не более питонский c способ, но первое, что пришло мне в голову

import pandas as pd

df = pd.read_csv('mbti_1.csv')

# assing unique id to each type
ids = list(enumerate(df['type'].unique()))
ids = dict((y, x+1) for x, y in ids)

df2 = pd.DataFrame(columns=['target', 'type', 'post'])
for _, row in df.iterrows():
    posts = row['posts'].split('|||')
    for post in posts:
        if 'http' not in post:
            df2.loc[len(df2)] = [ids[row['type']], row['type'], post]

print(df2.sample(10))
...