Использование to-отчетов при создании агентов из CSV-файла

Мой вопрос немного длинный. Я очень ценю это, если Вы могли прочитать это все, и я был бы очень благодарен за любой совет.

У меня есть данные, относящиеся к 2 потребителям как черепахам, которые оценили характеристики ноутбуков. Ноутбуки имеют 2 вида характеристик: размер экрана и время автономной работы. Каждый имеет несколько уровней. Например, срок службы батареи составляет 5 часов, 12 часов, 24 часа, 30 часов. Данные хранятся в файле csv.

   12 13.5 14 15 5 12 24 30
1  1   2    1  3 2  2  4  5
2  4   3    1  2  1 1  2  3

Я хочу суммировать показатели 2-х уровней характеристик. Например, для потребителя 1 и 2, что такое:

Суммарный показатель размера экрана 13,5 + показатель времени автономной работы 24

Поскольку 13,5 и 24 могут измениться позже, и я хочу узнать, например, сумму ставок размера 14 и времени автономной работы 5, я определил две функции с помощью «to-reports». Кроме того, поскольку, например, значение «12» дважды встречается в строке заголовка и представляет как размер, так и время автономной работы, я сделал 2 подмножества CSV-файла: одно для размера экрана, другое для батареи.

   12 13.5 14 15 
1  1   2    1  3 
2  4   3    1  2  

   5 12 24 30
1  2  2  4  5
2  1 1  2  3

Сначала в основной программе считывается файл csv, и каждой строке назначается черепаха, ожидая наличия двух потребителей.

to setup
  ca
  reset-ticks
  file-close-all
  file-open "turtle_details.csv"
 let headerrow csv:from-row file-read-line
 set Sc 13.5   ; at the beginning I want the rate of this screen size
 set Bat 24
   while [ not file-at-end? ] [
    let data csv:from-row file-read-line
      create-consumers 1 [
         set shape "person"
         set k k + 1
       print  obtain-Sc (Sc) + obtain-Bat (Bat)
      ]
   ]
  file-close-all
end

Я предположил, что сначала читается первая строка и генерируется потребитель. Теперь он переходит к отчету, чтобы найти get-Screen(13.5), который равен 2, но я подумал, что в следующий раз, когда obrain_Screen будет вызван, снова откроется csv, и курсор все еще будет в начале, но я хочу, чтобы он читал второй ряд. И чтобы продлить его, мне может понадобиться, чтобы он шел все дальше и дальше. Чтобы решить эту проблему, я определил счетчик k, который, например, проверяет это условие в первый раз: idx = 0 ‹ k =1, поэтому читается первая строка. Тогда idx = idx + 1 , так что больше ничего не делается.

to-report obtain-Screen[Sc]
  file-close-all ; close all open files

  file-open  "turtle_detailsSc.csv" 
  let headings csv:from-row file-read-line
  ifelse  is-number? position Sc headings
    [
      while [idx < k ]
      [ set fdata csv:from-row file-read-line
        set idx idx + 1
      ]
      report item position Sc headings fdata
]
[report 0.000000009]

Что-то похожее на Бат. Но он не работает и имеет ошибки. Есть идеи, как улучшить to-отчеты? Спасибо

Изменить

Учитывая, что набор данных выглядит следующим образом:

   size12  size13.5  size14  size15  Battery5  Battery12 Battery24 Battery30 
1  1        *2*         1      3        2         2           *4*       5
2  4        3           3      2        1          1           2        3

Теперь я могу получить доступ к набору данных и для каждого потребителя найти их оценку ноутбука, который они приобрели. Например, у потребителя 1 есть ноутбук размером 13,5 и временем автономной работы 24.

Consumer 1 evaluation of size 13.5 = 2
Consumer 1 evaluation of battery 24 = 4
Overall evaluation of laptop = 2 + 4 = 6

Я определил процедуру «Найти Eval», которая, когда мне нужно узнать оценку различных потребителей, позволяет мне получить доступ к набору данных и найти значения.

Чтобы лучше объяснить данные в таблице, у потребителя есть ноутбук, поэтому он может довольно хорошо его оценить, но по другим характеристикам, таким как то, как он оценивает ноутбук с размером экрана 15, он может получить некоторое представление или просто услышать от других, что он заполнил таблицу.

Я хочу сохранить этих двух потребителей и следить за их отношением к функциям ноутбука в течение 20 лет. Через год 2 потребитель 1, возможно, обновил свою систему, так что теперь его время автономной работы составляет 30. На этот раз мне нужно получить доступ к набору данных и вычислить

Consumer 1 evaluation of size 13.5 = 2

плюс

Consumer 1 evaluation of battery 30 = 5



  Overall evaluation of laptop = 2 + 5 = 7

На этот раз мне нужно найти значение для батареи 30. Я думаю, что когда я буду повторять свой код в течение 20 лет, create-consumer будет повторяться каждый раз, когда я хочу работать с набором данных, поэтому вместо того, чтобы держать 2 потребителей, каждый год будут создаваться новые потребители и полностью замещаться прежние.

Вопрос в том, как я могу создать потребителей один раз, но иметь доступ к любой точке данных в наборе данных много раз?

Большое спасибо,


person user710    schedule 29.06.2017    source источник
comment
Проблема заключается в том, что первая строка читается, но get-Sc (Sc) + get-Bat (Bat), что равно 6 для черепахи 1, печатается бесконечно. Для потребителя 2 не рассчитывается.   -  person user710    schedule 29.06.2017
comment
Если вы получаете бесконечный цикл, ваш цикл while может работать не так, как вы ожидаете. Что такое FE в вашем to-report? Кроме того, когда вы говорите, что 13.5 и 24 могут измениться позже, вы имеете в виду, что вы будете изменять эти значения в Netlogo или что вы будете перезагружать файл csv?   -  person Luke C    schedule 29.06.2017
comment
Спасибо за ответ. Извините, FE был опечаткой на самом деле. Отправляю в to-report Sc (для размера экрана) который равен 13.5, колонка со значением в шапке найдена. Тогда для потребителя один, 2 должны быть возвращены, а в следующий раз 3. Да, по netlogo. Я могу заметить, что оценки для Sc = 13,5 совершенно неудовлетворительны, поэтому следует установить стратегию Sc = Sc - 1,5, чтобы увидеть, как будут меняться мнения потребителей. Теперь функция get_Sc должна найти значение для Sc = 12, а не 13,5.   -  person user710    schedule 30.06.2017
comment
Понял Люк :) Заметил, что счетчик работает некорректно. С некоторыми подобными изменениями это работает хорошо :) После выхода из этого цикла счетчик должен быть уменьшен, чтобы, когда мы вернемся к нему, он работал: set idx idx - 1. Также я добавил set kk kk + 1 для второго к -отчеты по основной программе. Спасибо за помощь.   -  person user710    schedule 30.06.2017
comment
О, хорошо, рад, что ты это понял!   -  person Luke C    schedule 30.06.2017


Ответы (1)


В ответ на ваш комментарий - понял, подумал, что может быть так. Я представлю альтернативный подход, который может вам подойти или не подойти, но, вероятно, я бы решил эту проблему. Основное отличие состоит в том, что я бы сохранил списки рейтингов экрана и батареи в переменной черепахи, чтобы вы могли легко получить к ним доступ постфактум без необходимости отслеживать счетчики. Учитывая эти объявления переменных:

extensions [ csv ]

globals [ screen-headings battery-headings]

turtles-own [ 
  turtle-screen-list 
  turtle-battery-list
  turtle-screen-eval
  turtle-bat-eval
  turtle-sum-eval
  turtle-row-number
]

Я бы разделил заголовки CSV-файла на глобальные переменные screen-headings и battery-headings.

Затем я перебирал следующие строки csv, как вы сделали ниже, и разделял строки аналогичным образом, но на turtles-own переменные turtle-screen-list и turtle-battery-list. Таким образом, каждая черепаха знает свои собственные рейтинги для каждого экрана и батареи, поэтому вы можете изменить оцениваемый экран или батарею по мере необходимости.

Установите интересующий экран и батарею с помощью screen-to-evaluate и battery-to-evaluate (или используйте Chooser в интерфейсе), затем используйте генератор отчетов (аналогичный тому, что вы настроили), который проверяет положение интересующей батареи и экрана, чтобы вернуть текущую черепаху. рейтинг для каждого - это установит turtle-screen-eval и turtle-bat-eval. Наконец, суммируйте эти два последних значения.

to setup
  ca
  reset-ticks
  file-close-all
  file-open "turtle_details.csv"
  let headings csv:from-row file-read-line
  set screen-headings sublist headings 0 4
  set battery-headings sublist headings 4 length headings

  let screen-to-evaluate 13.5
  let battery-to-evaluate 24

  while [ not file-at-end? ] [
    let data csv:from-row file-read-line
    create-turtles 1 [
      set turtle-screen-list sublist data 0 4
      set turtle-battery-list sublist data 4 length data
      set turtle-screen-eval turtle-screen-rating screen-to-evaluate
      set turtle-bat-eval turtle-battery-rating battery-to-evaluate
      set turtle-sum-eval turtle-screen-eval + turtle-bat-eval
    ]
  ]
  file-close-all

end

to-report turtle-screen-rating [sc]
  let pos position sc screen-headings
  let turt-screen-rate-value item pos turtle-screen-list
  report turt-screen-rate-value
end

to-report turtle-battery-rating [bc]
  let pos position bc battery-headings
  let turt-bat-rate-value item pos turtle-battery-list
  report turt-bat-rate-value
end

Конечно, вы можете уплотнить некоторые из них по мере необходимости. Я протестировал эту настройку с 4 строками (по образцу данных вашего примера), и, похоже, она работает нормально. Если у вас огромное количество строк, это может не сработать.

Изменить:

Если вы в конечном итоге замените screen-to-evaluate и battery-to-evaluate средствами выбора интерфейса (что я рекомендую — это позволяет вам быстро увидеть различные значения), вы можете обновить до новых значений с помощью чего-то вроде:

to update-vals
  ask turtles [
    set turtle-screen-eval turtle-screen-rating scrn
    set turtle-bat-eval turtle-battery-rating batr
    set turtle-sum-eval turtle-screen-eval + turtle-bat-eval
  ]
end

где scrn и batr — имена выбирающих.

Или, если вы хотите, чтобы они динамически обновлялись, вы можете сделать монитор интерфейса, который сообщает следующий репортер:

to-report update
ask turtles [
    set turtle-screen-eval turtle-screen-rating scrn
    set turtle-bat-eval turtle-battery-rating batr
    set turtle-sum-eval turtle-screen-eval + turtle-bat-eval
  ]
  report "Dynamically updating."
end

В этом случае, как только вы измените значение Chooser, черепахи должны немедленно обновить свои turtle-bat-eval, turtle-screen-eval и turtle-sum-eval. Весело!

Изменить 2

Если ваш csv включает столбец для номеров строк, например:

row 12 13.5 14 15  5 12 24 30
1   1  2.0  1  3  2  2  4  5
2   4  3.0  1  2  1  1  2  3

Я бы рекомендовал создать переменную черепахи для хранения используемого номера строки. Теперь я включил один под названием turtle-row-number. Затем вам просто нужно будет включить строку для обновления этой переменной из элемента first в списке, который является номером строки, а затем соответствующим образом изменить ваши значения sublist на что-то вроде:

to setup-row-nums
  ca
  reset-ticks
  file-close-all
  file-open "turtle_details_2.csv"
  let headings csv:from-row file-read-line
  set screen-headings sublist headings 1 5
  set battery-headings sublist headings 5 length headings

  while [ not file-at-end? ] [
    let data csv:from-row file-read-line
    create-turtles 1 [
      set turtle-row-number first data 
      set turtle-screen-list sublist data 1 5
      set turtle-battery-list sublist data 5 length data
    ]
  ]
  update-vals
  file-close-all

end

Где update-vals как показано выше.

person Luke C    schedule 29.06.2017
comment
Большое спасибо. Звучит так интересно. Я посмотрю, работает ли это с моим набором данных. - person user710; 30.06.2017
comment
Хорошо, но я не буду слишком расстроен, если вы выберете тот, который у вас уже есть! Ваше здоровье. - person Luke C; 30.06.2017
comment
Я нашел идею разделения заголовков, определения черепах и всего остального настолько увлекательной, что пришел к выводу, как работает ваш код. Учитывая, что подсписок x y сообщает список, начинающийся с x, но не включающий y, не должны ли они измениться следующим образом: set screen-headings sublist headers 0 4 set battery-headings sublist headers 4 length + 1 headers? Другой вопрос, что первый столбец, включающий номер каждой строки, включен в первый подсписок, но не в другой, верно? Спасибо - person user710; 30.06.2017
comment
Эй, рад, что это может сработать. И да, если ваш CSV-файл включает номера строк в столбце, я считаю, что вы правы на 100%. Мой файл csv вообще не включает номера строк в сохраненном файле, поэтому, когда я sublist data 0 4 и sublist data 4 length headings, он просто берет значения из необходимых столбцов (столбцы 0, 1, 2 и 3 и столбцы 4, 5, 6, и 7 соответственно). Если ваш файл содержит столбец с номером строки, я думаю, вам нужно сделать sublist data 0 5 to include it. - person Luke C; 30.06.2017
comment
Если вы также хотите включить этот номер строки во второй подсписок, я думаю, вы могли бы сделать что-то вроде set turtle-battery-list item 0 data turtle-battery-list (сразу после set turtle-battery-list sublist data 4 length data). Вам также придется настроить оба подсписка заголовков, чтобы сохранить позиции в порядке. Однако может быть проще вместо этого назначить номер строки отдельно другой переменной черепахи, которая может называться from-row или как-то еще, чтобы вы могли отслеживать, какая строка была назначена данной черепахе. Я обновил свой ответ, чтобы уточнить. - person Luke C; 30.06.2017
comment
Привет, я не могу отблагодарить вас за ваши ценные и чрезвычайно полезные советы. Ваш эффективный код был чрезвычайно полезен и работает необычайно хорошо :) Я был так взволнован, увидев, как он работает, что я еще не читал эти части обновления, но я почти уверен, что они сделают все более чудесным :) Большое спасибо. - person user710; 30.06.2017
comment
Право, я рад, что помог. Удачного кодирования! - person Luke C; 30.06.2017
comment
Спасибо большое :) - person user710; 02.07.2017
comment
У меня есть еще один вопрос о вашем коде. в то время как [ не файл в конце? ] [ let data csv: from-row file-read-line create-turtles 1 [ Если я повторю функцию с этим кодом 20 раз, а в моем наборе данных будет 100 строк, представляющих потребителей, создаст ли create-turtle в целом 2000 черепах? Что, если я хочу иметь только 100 потребителей, но 20 раз обращаюсь к набору данных и нахожу разные значения для оценки? Спасибо - person user710; 14.07.2017
comment
Да, если вы повторите эту функцию (от file-open до file-close-all), это должно создать 2000 черепах. Чтобы уточнить, вы хотите 100 черепах, но только 20 из них имеют значения из набора данных? Или вы хотите рисовать из набора данных 20 раз, и эти 100 черепах выбирают случайным образом из 20 нарисованных строк, чтобы получить свои значения? - person Luke C; 14.07.2017
comment
Спасибо. позволь мне объяснить. У меня есть 100 потребителей, для которых у меня есть набор данных об их предпочтениях в отношении различных уровней некоторых атрибутов, таких как размер и цена. Я хочу следить за этими потребителями в течение 20 лет. В первый год они что-то купили и отдали предпочтение каким-то атрибутам. В следующем году они могут выразить свои предпочтения для некоторых других уровней, которые мне нужны, чтобы снова получить доступ к набору данных, чтобы найти их оценку на основе некоторых других значений в наборе данных. Вроде как create-consumer используется один раз, но к набору данных можно обращаться 20 раз для одних и тех же агентов. - person user710; 14.07.2017
comment
Боюсь, я все еще не совсем понимаю. Вы имеете в виду, что хотите, чтобы потребители во втором году вернулись и выбрали совершенно новый набор предпочтений? - person Luke C; 14.07.2017
comment
Извините, что плохо объяснил. Могу ли я добавить больше вещей к моему вопросу, который уже был решен вашим ответом? - person user710; 14.07.2017
comment
Насколько я знаю, вы все еще можете! - person Luke C; 14.07.2017
comment
Давайте продолжим обсуждение в чате. - person user710; 14.07.2017