2017-02-19 6 views
1

У меня есть длинная (CSV-файл) с «именем-столбца й значением» пара, которые я хотел бы прочитать в pandas.DataFrameчтение CSV с парами значений имени-столбца х

user_id col val 
00008901 1 55 
00008901 2 66 
00011501 1 77 
00011501 3 88 
00011501 4 99 

Результат должны выглядеть следующим образом:

   1 2 3 4 
00008901 55 66 0 0 
00011501 77 0 88 99 

Я пытался читать его в список и создать DataFrame от него, но панды разбился, как у меня есть 4,5 миллиона элементов.

Какой лучший способ сделать это? Идеально прямо с read_csv.

ответ

1

Первое использование read_csv для создания DataFrame:

df = pd.to_csv('file.csv') 

Затем нужно set_index с unstack:

df1 = df.set_index(['user_id','col'])['val'].unstack(fill_value=0) 
print (df1) 
col  1 2 3 4 
user_id     
8901  55 66 0 0 
11501 77 0 88 99 

Другое решение с pivot, заменив NaN на 0 по fillna и последним броском к int:

df1 = df.pivot(index='user_id', columns='col', values='val').fillna(0).astype(int) 
print (df1) 
col  1 2 3 4 
user_id     
8901  55 66 0 0 
11501 77 0 88 99 

Если получить сообщение об ошибке:

"ValueError: Index contains duplicate entries, cannot reshape"

Это означает, что у вас есть несколько дубликатов, поэтому быстрое решение является groupby с unstack и некоторые aggreagte функции, как mean или sum:

print (df.groupby(['user_id','col'])['val'].mean().unstack(fill_value=0)) 
col  1 2 3 4 
user_id     
8901  55 66 0 0 
11501 77 0 88 99 

Лучше это увидеть в немного изменился csv:

print (df) 
    user_id col val 
0  8901 1 55 
1  8901 2 66 
2 11501 1 77 > duplicates -> 11501 and 1 
3 11501 1 151 > duplicates -> 11501 and 1 
4 11501 3 88 
5 11501 4 99 


print (df.groupby(['user_id','col'])['val'].mean().unstack(fill_value=0)) 
col  1 2 3 4 
user_id     
8901  55 66 0 0 
11501 114 0 88 99 

На самом деле я думал, что у меня нет дубликатов, но выяснил, что у меня действительно есть ... Я не мог использовать «.mean», поскольку он является категориальным значением, но решил, е проблема сначала смотрит на отсортированную таблице, а затем просто держать последнюю запись ... затем применяя (большое!) решения .. который я до сих пор в полной мере понять ;-)

df.sort(columns=(['user_id','col'])) # optional for debugging 
df.drop_duplicates(subset=['user_id','col'], keep='last', inplace=True) 
df_table = df.set_index(['user_id','col'])['val'].unstack(fill_value=0) 
+0

Вау, это уже крутой подход, которого я не нашел за несколько дней! Проблема в том, что я получаю сообщение об ошибке при распаковке> «ValueError: Index содержит повторяющиеся записи, не может изменить форму» –

+0

См. Обновленное решение, я пытаюсь объяснить проблему и получить решение. – jezrael

+0

Отличное решение, которого я не мог найти за несколько дней! Большое спасибо! –

0

Я не думаю, что можно использовать read_csv для анализа файла csv.

Вы можете создать структуру данных, такие как словарь и использовать его для создания dataframe:

import pandas as pd 
from collections import defaultdict 
import csv 

data_dict = defaultdict(lambda: [0] * columns) 
columns = 4 
delimiter = ',' 

with open("my_csv.csv") as csv_file: 
    reader = csv.DictReader(csv_file,delimiter=delimiter) 
    for row in reader: 
     row_id = row["user_id"] 
     col = int(row["col"])-1 
     val = int(row["val"]) 
     data_dict[row_id][col] = val 

df = pd.DataFrame(data_dict.values(), index=data_dict.keys(), columns=range(1, columns+1)) 

Для CSV-файл, который содержит:

user_id,col,val 
00008901,1,55 
00008901,2,66 
00011501,1,77 
00011501,3,88 
00011501,4,99 

Выхода:

  1 2 3 4 
00008901 55 66 0 0 
00011501 77 0 88 99 
1

Вы не можете непосредственно читается в требуемой структуре, используя read_csv. Но вы можете использовать функцию pivot_table для преобразования в нужную структуру.

df = pd.read_csv('filepath/your.csv') 
df = pd.pivot_table(df, index='user_id', columns='col', values='val, aggfunc='mean').reset_index() 

The output will be like 
      1 2 3 4 
00008901 55 66 0 0 
00011501 77 0 88 99 
+0

Похож на интересную альтернативу. В моем случае я просто не могу использовать «mean», поскольку у меня есть категориальные ценности, но нужно просто сохранить последний (см. Выше). –

Смежные вопросы