-1

我从 Kickstarter.com 抓取数据。数据格式为 CSV,标题为“backer”和“backed_projects”。“支持者”列存储支持者的所有个人资料 url,“backed_projects”列存储支持者支持的项目列表。该列表由分号分隔。我想在 Gephi 中制作一个网络图,看看是否有一群支持者倾向于支持相同的项目。在图中,如果两个支持者支持同一个项目,他们将通过一条边连接。数据的输入格式必须是支持者和支持相同项目的支持者。

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

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

4

1 回答 1

0

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

我将假设一个像这样的输入文件(“input”)(其中 url 现在是名称):

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 格式,这些似乎是边缘

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

我不记得 awk/gawk 是否预先消耗了整个文件。如果输出没问题,那么将每一行处理成多行将适用于许多其他语言。


好的 - 虽然我仍然认为我的第一次尝试更有用,但这是第二个版本,其中所有内容都被稍微重写并包括一个新的 gawk 来制作点文件有向图输出(这让我可以在 Yed 中查看它 - 见评论)。

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

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

用以下内容制作一个可执行文件(我称之为“explode”):

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 -> 与同一项目关联的用户列表”

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

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

于 2013-04-11T00:10:05.420 回答