2015-06-08 3 views
2

Я пытаюсь сделать что-то, что, вероятно, не так сложно в Python (2.7.6), но я нигде не приближаюсь к решению. Это относится к эксперименту fMRI (в частности, к истечению срока годности). У меня есть CSV-файл, который выглядит примерно так:python csv для вложенных списков, счетчик

level,string,key 
1,string11,1 
1,string12,0 
1,string13,1 
2,string21,1 
2,string22,1 
2,string23,0 

Есть 20 уровней (1:20), то CSV имеет около 5000 записей. То, что я хотел бы сделать, представляет строку из второго столбца с определенного уровня (начальный уровень определяется заранее). Так, например, мы протестировали объект и определили, что они начнутся на уровне 5. Случайная строка представлена ​​на уровне 5 (например, «корова - это животное»). Субъект нажимает кнопку для истинного/ложного (ответ в колонке «ключ» - 1/0). Сложный бит состоит в том, что каждые 4 последовательных правильных ответа уровень увеличивается на 1, неправильный ответ уменьшает уровень на 1.

Сроки/эффективность несколько важны, поэтому я думал, что csv можно проанализировать заранее, часть работы во время эксперимента - это просто доступ к данным, хранящимся на уровне. Я посмотрел на вложенные словари, похоже, не прав. Возможно, вложенные списки? Я немного из глубины. Я написал рабочий пример в bash, если это более ясно, чем мое объяснение.

#!/bin/bash 

csv="file.csv" 
level="5" 
ilevel="0" 
counter="1" 

while [ "$counter" -le 10 ]; do 
    stim=$(awk -F',' -v l="$level" '{if($1==l) print $2","$3}' "$csv"|sort -R|head -n1) 
    stim1=$(echo "$stim"|cut -d',' -f1) 
    stim2=$(echo "$stim"|cut -d',' -f2) 
    read -p "$stim1 (t/f): " ANS 
    if [[ "$stim2" == "1" && "$ANS" == "t" || "$stim2" == "0" && "$ANS" == "f" ]]; then #if correct 
     ilevel=$(echo "scale=2;$ilevel+.25"|bc) #add .25 to ilevel counter 
     if [[ "$ilevel" == "1.00" ]]; then 
      if [[ "$level" < "20" ]]; then 
       level=$(echo "$level+1"|bc) #increase level 
      fi 
      ilevel=0 
     fi 
    else 
     if [[ "$level" > "1" ]]; then #if incorrect 
      level=$(echo "$level-1"|bc) #decrease level 
     fi 
     ilevel=0 
    fi 
    let "counter += 1" 
done 

Баш скрипт только для целей рабочего примера - счетчик, печать на экран, пользователь обратной связи .. это все обрабатывается по-разному в реальности, и это уже сделано. Мне просто нужно выяснить сортировку csv и манипулировать уровнем. Спасибо заранее за любые предложения.

+0

Я все еще не понимаю. Что именно вы хотите сделать, манипулируя доступным рабочим CSV-файлом? Не могли бы вы вручную показать, что вы подразумеваете под манипуляцией? – Mehdi

+0

Спасибо за ваш комментарий, но я не думаю, что я могу объяснить это лучше, и пример bash показывает общую идею. – user4987992

ответ

1

Чтобы сгруппировать строки использовать Dict и использовать random.choice, чтобы выбрать случайную строку:

from collections import defaultdict 
import csv 
from random import choice 
d = defaultdict(list) 


with open("in.csv") as f: 
    next(f) 
    r = csv.reader(f) 
    for row in r: 
     d[int(row[0])].append(row[1]) 


level = 2 

ch = choice(d[level]) 
print(ch) 
string21 

Если вам нужен ответ/столбец 2:

from collections import defaultdict 

d = defaultdict(defaultdict) 

with open("in.csv") as f: 
    next(f) 
    r = csv.reader(f) 
    for row in r: 
     d[int(row[0])][row[1]] = row[2] 

from pprint import pprint as pp 
pp(dict(d)) 
level = 2 
ch = choice(list(d[level])) 
ans = d[level][ch] 
print(ch,ans) 

Выход:

# main dict keys are levels, nested dict contain key/value pairing 
# question and answer 
{1: defaultdict(None, {'string11': '1', 'string12': '0', 'string13': '1'}), 
2: defaultdict(None, {'string21': '1', 'string23': '0', 'string22': '1'})} 

Основные ключи ключей - это уровни, вложенные диктофоны содержат все строки уровня, которые являются ключами гнезда ed dicts, а значения - в столбце 3 ответа.

Если вы используете графический интерфейс, который, кажется, вы ваша логика будет что-то вроде следующего, но, очевидно, используя свои методы GUI:

level = 2 
streak = 0 
# current level questions 
level_choice = list(d[level]) 

while True: 
    # pick random string/question 
    ch = choice(level_choice) 
    # correct answer 
    ans = d[level][ch] 
    inp = raw_input("ask questions using ch") 
    # if answer is correct increment streak 
    if inp == ans: 
     streak += 1 
    else: 
     # else it is wrong, drop a level and update variables 
     level -= 1 
     streak = 0 
     level_choice = list(d[level]) 
    # if we have four in a row, up level ad again update variables 
    if streak == 4: 
     level += 1 
     streak = 0 
     level_choice = list(d[level]) 

Очевидно, что должен наступить момент, когда многочисленные ответы, которые неправы будет означает, что уровень достигает 0, так что может быть время для разрыва, эту логику вам придется решать. Если вам не нужны повторяющиеся вопросы, вам придется удалить их из dict.

+0

Спасибо за ваш комментарий, я получаю эту ошибку 'd [int (строка [0])] [строка [1]] = строка [2]; TypeError: индексы списка должны быть целыми числами, а не str' – user4987992

+0

@ user4987992, извините, забыли добавить импорт и обновленную структуру dict –

+0

Спасибо! Прекрасно работает – user4987992

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