将~500mb csv文件转换为邻接列表

时间:2013-04-10 23:23:45

标签: csv mapreduce adjacency-list large-data

我从Kickstarter.com上删除了数据。数据格式为CSV,标题为“backer”和“backed_projects”。 “backer”列存储支持者的所有配置文件URL,“backed_projects”列存储支持者支持的项目列表。该列表以分号分隔。我想在Gephi中制作一个网络图,看看是否有支持者群集倾向于支持相同的项目。在图表中,如果两个支持者支持同一个项目,则它们将通过边缘连接。数据的输入格式必须是支持者和支持相同项目的支持者。

我不确定如何将原始大型CSV文件处理为格式支持者 - >支持相同项目的支持者列表。有什么建议?

任何人都知道使用map reduce的有效方法吗?

1 个答案:

答案 0 :(得分:0)

我认为gawk不一定能处理这500mb,但你可以在大多数语言(java,perl等)中完成同样的事情。我还假设只是列出边缘很好,而不是将它们重新编译成一行。

我会假设一个像这样的输入文件(“输入”)(网址现在是名字):

joe;proj2,proj9,pro8
erin;proj1,proj7,pro8
sue;proj47,pro7
elmo;pro7

运行以下内容:

cat input | gawk -F"," '{
    split( $1, arr, ";" );
    printf( "%s;%s\n", arr[1], arr[2] );
    for( i = 2; i <= NF; i++ ) { printf( "%s;%s\n", arr[1], $i ); }
}'

产生以下输出:

joe;proj2
joe;proj9
joe;pro8
erin;proj1
erin;proj7
erin;pro8
sue;proj47
sue;pro7
elmo;pro7

根据gephi csv-formats

,它们似乎是边缘

或者您可以进一步处理输出。

我不记得是否或现在awk / gawk预先消耗整个文件。如果输出正常,那么将每一行处理成多个可以在许多其他语言中使用。


好的 - 虽然我仍然认为我的第一次尝试更有用,但这是第二个版本,其中所有内容都略有改写,并包含一个新的gawk来制作点文件有向图输出(这让我在Yed中查看它 - 请参阅注释)

“输入”文件(首次尝试中的拼写错误在“proj”中删除了“j”):

joe;proj2,proj9,proj8
erin;proj1,proj7,proj8
sue;proj47,proj7
elmo;proj7

制作以下可执行文件(我称之为“爆炸”):

gawk -F"," '
{
count = split( $1, sc, ";" ); 
printf( "%s %s\n", sc[2], sc[1] ); 
for( i = 2; i <= NF; i++ ) { printf( "%s %s\n", $i, sc[1] ); }
}
'

更改输出或原始gawk,因为它将用于排序/提供下一个gawk脚本(另一个可执行文件;我称之为“组合”):

gawk -F" " '
BEGIN { printf( "digraph similar_users (\n" );
    project_name = "";
    users = "";
    }

{
if( $1 ~ project_name )
    build_users_string( $2 );
else {
    make_user_nodes( users );
    users = "";
    build_users_string( $2 );
    }
project_name = $1
}

function build_users_string( u )
{
    users = sprintf( "%s%s%s", users, length( users ) == 0 ? "" : " ", u );
}

function make_user_nodes( u )
{
    if( (count = split( u, arr, " " )) <= 1 )
        return 1;
    for( i = 1; i <= count; i++ )
        {
        printf( "%s -> ", arr[ i ] );
        for( j = 1; j <= count; j++ )
            if( j != i )
                {
                end = (i == count ) ? count-1 : count;
                printf( "%s%s", arr[j], j != end ? "," : ";\n" );
                }
        }
    return( count );
}

END { make_user_nodes( users );
    printf( ")\n" );
    }
'

从“explode”脚本中读取已排序的输入文件,运行时如下:

cat input | explode | sort | combine > output.dot

生成文件“output.dot”,其中“user - &gt;与同一项目相关联的用户列表”

digraph similar_users (
elmo -> erin,sue;
erin -> elmo,sue;
sue -> elmo,erin;
erin -> joe;
joe -> erin;
)

使用的内存应该与上一个脚本中的排序和最大的项目/用户转换一样糟糕,因为只有在项目名称更改时,它才会处理按项目分组的用户。更加记忆密集的“单次通过”会将所有用户放入项目的地图中 - > (用户列表)并在最后完成地图的所有处理。请注意,指向单个项目的用户将被删除。