我使用D3和JavaScript来操作一些csv数据。这个想法是它记录了人们全天去的地方:他们可能从家里开始,去杂货店,学校,工作等。每当有人从他们所在的位置移动时,都会记录csv文件中的新行。因此,当莎莉醒来时,它会记录Sally,home
,当她离开学校时,它会记录Sally,school
等。这些地方是任意的,可以按任何顺序进行,并且可能有更多的地方。
我的csv文件如下所示:
name,place
Sally,home
Joe,home
Bill,work
Joe,work
Sally,school
Sally,grocery
Bill,salon
Joe,grocery
我想在同一个人的下一步为每一行添加一列。从本质上讲,我希望数据反映home
和school
之间,school
和grocery
之间的转换,或者相邻步骤之间的转换。在第一个数据点,莎莉在家,下次她被提及,她在学校。因此,我希望第一个数据点(而不仅仅是Sally, home
)更改为Sally, home, school
以反映转换。所以,经过操作后,上面应该是这样的:
name,place,next
Sally,home,school
Joe,home,work
Bill,work,salon
Joe,work,grocery
Sally,school,grocery
Sally,grocery
Bill,salon
Joe,grocery
然后,我想删除每个人的最后一步:基本上,任何没有" next"列(这些可能并不总是最后三行)。最终结果如下:
name,place,next
Sally,home,school
Joe,home,work
Bill,work,salon
Joe,work,grocery
Sally,school,grocery
我唯一的想法是使用嵌套for循环来查找下一个匹配的名称,然后以某种方式添加新列...这是我的尝试,但你不能只是声明一个新的列
d3.csv("data.csv", function(error, data) {
for(i=0; i<data.length; i++){
for(j=0; j<data.length; j++){
if (data[i].name === data[j].name){
data[i].next = data[j].place;
break;
}
}
}
});
任何指向正确方向的人都会非常感激(最终目标是能够将此流程放入D3的Sankey图中,如果有帮助的话)。
答案 0 :(得分:1)
你是什么意思“但你不能只声明一个像这样的新列?是的,你可以(当然,我正在考虑数据阵列,这是你要使用的,而不是实际的CSV。但是,如果你真的想要保存一个新的CSV文件,请相应地编辑您的问题并删除D3标签,因为D3没有相应的方法。)
我要在代码中做的唯一更改是在外部(j
)循环之后的一个位置开始内部(i
)循环:
for (i = 0; i < data.length; i++) {
for (j = i + 1; j < data.length; j++) {
if (data[i].name === data[j].name) {
data[i].next = data[j].place;
break;
}
}
}
然后,我们删除没有next
属性的对象:
var finalData = data.filter(function(d) {
return d.next
});
以下是您的数据演示:
var data = d3.csvParse(d3.select("#csv").text());
for (i = 0; i < data.length; i++) {
for (j = i + 1; j < data.length; j++) {
if (data[i].name === data[j].name) {
data[i].next = data[j].place;
break;
}
}
}
var finalData = data.filter(function(d) {
return d.next
});
console.log(finalData)
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="csv">name,place
Sally,home
Joe,home
Bill,work
Joe,work
Sally,school
Sally,grocery
Bill,salon
Joe,grocery</pre>
答案 1 :(得分:-1)
是的我知道,这是C#而非Javascript,就像你问题上的标签一样。虽然我最擅长C#,但我很匆忙,我想帮忙...所以这里有一个你可以在Javascript中重新设定的概念。
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.IO;
namespace ManipulatingCSV_45044259
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
/*here I'm just making a list of string that basically represents each line of your file*/
List<string> textlines = new List<string>();
textlines.Add("name,place");
textlines.Add("Sally, home");
textlines.Add("Joe,home");
textlines.Add("Bill, work");
textlines.Add("Joe,work");
textlines.Add("Sally, school");
textlines.Add("Sally,grocery");
textlines.Add("Bill, salon");
textlines.Add("Joe,grocery");
Dictionary<string, string> cummulatedValues = new Dictionary<string, string>();
//iterates through the lines of text
foreach (string item in textlines)
{
string[] splitted = item.Split(',');//split using the delimiter
if (cummulatedValues.Keys.Contains(splitted[0]))
{
//we already have this person, lets add something to the entry
cummulatedValues[splitted[0]] += "," + splitted[1];
}
else
{
//this is a new person, lets create an entry
cummulatedValues.Add(splitted[0], splitted[1]);
}
}
//Now we'll write the new file.
using (StreamWriter sw = new StreamWriter("pathtofile.txt"))
{
foreach (KeyValuePair<string, string> item in cummulatedValues)
{
/*Since you want only people who have been to more than 1 place*/
if (item.Value.Split(',').Length > 1)
{
//if there are more than 1 place listed
sw.WriteLine(item.Key + "," + item.Value);//write the line
}
}
}
}
}
}