wolfram-mathematica - exchange - mathematica descargar
¿Cómo accedo a la API de StackOverflow desde Mathematica? (2)
El otro día me preguntaba si StackOverflow tenía una API a la que podía acceder desde Mathematica, y aparentemente la tiene: "Guardando anotaciones de trama"
¿Cuál es la mejor manera de obtener datos de StackOverflow en Mathematica? Sjoerd usó la información para hacer una trama. Estoy interesado en agregar notificaciones relacionadas con SO en una celda acoplada que guardo en mis cuadernos, así puedo saber cuándo hay actualizaciones o respuestas sin salir de Mathematica.
Brett, no relacionado con la API de SO, pero podría usar la fuente RSS para las nuevas preguntas etiquetadas de Mathematica. Aquí está mi implementación ingenua:
QuestionHyperlink[data_] :=
Function[{name, title, link},
Hyperlink[Tooltip[title, name], link]] @@ Join[
Cases[data,
XMLElement[
"author", _, {___, XMLElement["name", {}, {name_}], ___}] :>
name],
Cases[data, XMLElement["title", _, {title_}] :> title],
Cases[data, XMLElement["link", rules_, {}] :> ("href" /. rules)]]
Cases[Import[
"http://.com/feeds/tag?tagnames=mathematica&sort=/
newest", "XML"],
XMLElement["entry", attrs_, data_] :>
QuestionHyperlink[data], Infinity]
Por demanda popular, el código para generar el gráfico de los 10 principales respondedores de SO (excepto las annotations ) utilizando la API de SO (es una API bastante ordenada y completa; hay muchas novedades allí. Fácil también, vea mi código).
Actualización : se agregó App-key para garantizar que el código coopere mejor con el SO-API (mayor límite de llamadas diarias). Úsalo solo para esta aplicación.
Abril 2011
Agosto 2011
MMA 8 version! Versión MMA7 más abajo
getRepChanges[userID_Integer] :=
Module[{totalChanges},
totalChanges =
"total" /.
Import["http://api..com/1.1/users/" <>
ToString[userID] <> "/reputation?key=NgVJ4Y6vFkuF-oqI-eOvOw&fromdate=0&pagesize=1&page=1",
"JSON"
];
Join @@
Table[
"rep_changes" /.
Import["http://api..com/1.1/users/" <>
ToString[userID] <>
"/reputation?key=NgVJ4Y6vFkuF-oqI-eOvOw&fromdate=0&pagesize=100&page="
<> ToString[page],
"JSON"
],
{page, 1, Ceiling[totalChanges/100]}
]
]
topAnswerers =
({"display_name","user_id", "email_hash"} /. #) & /@
("user" /.
("top_users" /.
Import[
"http://api..com/1.1/tags/mathematica/top-answerers/all-time",
"JSON"
]
)
)
topAnswerers = {#, #2,
Import["http://www.gravatar.com/avatar/" <> #3 <> ".jpg?s=36&d=identicon&d=identicon"]
} & @@@ topAnswerers
repChangesTopUsers =
Table[
repChange =
ReleaseHold[
(
Hold[
{
DateList["on_date" + AbsoluteTime["January 1, 1970"]],
"positive_rep" - "negative_rep"
}
] /. #
) & /@ getRepChanges[userID]
] // Sort;
accRepChange = {repChange[[All, 1]],Accumulate[repChange[[All, 2]]]}/[Transpose],
{userID, topAnswerers[[All, 2]]}
];
pl = DateListLogPlot[
Tooltip @@@
Take[({repChangesTopUsers, Row /@ topAnswerers[[All, {3, 1}]]}/[Transpose]),
10], Joined -> True, Mesh -> None, ImageSize -> 1000,
PlotRange -> {All, {10, All}},
BaseStyle -> {FontFamily -> "Arial-Bold", FontSize -> 16},
DateTicksFormat -> {"MonthNameShort", " ", "Year"},
GridLines -> {True, None},
FrameLabel -> (Style[#, FontSize -> 18] & /@ {"Date", "Reputation",
"Top-10 answerers", ""})]
EDITAR
Tenga en cuenta que puede trazar hasta e incluir un top-20 cambiando el valor en la función Tomar. Se pone muy ocupado muy pronto.
Intenté mejorar un poco la legibilidad del código de marcado. Me temo que esto producirá algunos espacios espurios cuando se copie.
EDITAR
El tamaño de la página vuelve a 100 elementos / página ==> menos llamadas a la API. Tenga en cuenta que la primera llamada a la API es para determinar la cantidad de publicaciones que tiene el usuario. Estos datos están presentes sin importar el tamaño de la página, por lo que este se elige preferiblemente pequeño (10 o más, posiblemente 1, no se verificó). Luego, los datos se obtienen en páginas sucesivas hasta que se alcanza la última página. Puedes usar el tamaño máximo de página (100) para eso. Solo tenga cuidado de que el número máximo de páginas en el conteo de bucles se ajuste en consecuencia.
EDITAR: mejor código de MMA 7 (viernes 22 de abril)
MMA 7 no realiza importaciones JSON, así que hago una importación de texto en lugar de una traducción JSON. He probado esta versión varias veces (en MMA 8) y parece funcionar sin los errores que recibí ayer.
getRepChanges[userID_Integer] :=
Module[{totalChanges},
totalChanges =
"total" /.
ImportString[
StringReplace[(Import[
"http://api..com/1.1/users/" <>
ToString[userID] <>
"/reputation?key=NgVJ4Y6vFkuF-oqI-eOvOw&fromdate=0&pagesize=1&page=1", "Text"]), {":" ->
"->", "[" -> "{", "]" -> "}"}], "NB"];
Join @@
Table["rep_changes" /.
ImportString[
StringReplace[
Import["http://api..com/1.1/users/" <>
ToString[userID] <>
"/reputation?key=NgVJ4Y6vFkuF-oqI-eOvOw&fromdate=0&pagesize=100&page=" <> ToString[page],
"Text"], {":" -> "->", "[" -> "{", "]" -> "}"}],
"NB"], {page, 1, Ceiling[totalChanges/100]}]]
topAnswerers = ({"display_name", "user_id",
"email_hash"} /. #) & /@ ("user" /. ("top_users" /.
ImportString[
StringReplace[
" " <> Import[
"http://api..com/1.1/tags/mathematica/top-answerers/all-time", "Text"], {":" -> "->", "[" -> "{", "]" -> "}"}],
"NB"]))
topAnswerers = {#, #2,
Import["http://www.gravatar.com/avatar/" <> #3 <>
".jpg?s=36&d=identicon&d=identicon"]} & @@@ topAnswerers
repChangesTopUsers =
Table[repChange =
ReleaseHold[(Hold[{DateList[
"on_date" + AbsoluteTime["January 1, 1970"]],
"positive_rep" - "negative_rep"}] /. #) & /@
getRepChanges[userID]] // Sort;
accRepChange = {repChange[[All, 1]],
Accumulate[repChange[[All, 2]]]}/[Transpose], {userID,
topAnswerers[[All, 2]]}];
DateListLogPlot[
Tooltip @@@
Take[({repChangesTopUsers,
Row /@ topAnswerers[[All, {3, 1}]]}/[Transpose]), 10],
Joined -> True, Mesh -> None, ImageSize -> 1000,
PlotRange -> {All, {10, All}},
BaseStyle -> {FontFamily -> "Arial-Bold", FontSize -> 16},
DateTicksFormat -> {"MonthNameShort", " ", "Year"},
GridLines -> {True, None},
FrameLabel -> (Style[#, FontSize -> 18] & /@ {"Date", "Reputation",
"Top-10 answerers", ""})]
EDITAR: funciones auxiliares para filtrar etiquetas de publicación. Estas funciones se pueden usar para filtrar las ganancias de reputación, con el fin de encontrar ganancias solo para ciertas etiquetas. tagLookup
obtiene un entero post_ID como entrada y genera las etiquetas de la publicación específica. getQuestionIDs
y getAnswerIDsFrom...
van a la inversa. Dada una etiqueta, encuentran todas las ID de pregunta y respuesta para que uno pueda probar con MemberQ
si un post_ID dado pertenece a esta etiqueta. Tanto tagLookup como getAnswerIDs son lentos ya que son necesarias muchas llamadas de API. No pude probar las dos últimas funciones ya que el acceso a la API está inactivo o mi IP ha sido bloqueada.
tagLookup[postID_Integer] :=
Module[{im},
im = Import["http://api..com/1.1/questions/" <> ToString[postID],"JSON"];
If[("questions" /. im) != {},
First[("tags" /. ("questions" /. im))],
im = Import["http://api..com/1.1/answers/" <> ToString[postID],"JSON"];
First[("tags" /. ("questions" /. Import["http://api..com/1.1/questions/" <>
ToString[First["question_id" /. ("answers" /. im)]], "JSON"]))]
]
]
getQuestionIDs[tagName_String] := Module[{total},
total =
"total" /.
Import["http://api..com/1.1/questions?tagged=" <>
tagName <> "&pagesize=1", "JSON"];
Join @@
Table[("question_id" /. ("questions" /.
Import["http://api..com/1.1/questions?key=NgVJ4Y6vFkuF-oqI-eOvOw&tagged=" <>
tagName <> "&pagesize=100&page=" <> ToString[i],
"JSON"])), {i, 1, Ceiling[total/100]}]
]
getAnswerIDsFromQuestionID[questionID_Integer] :=
Module[{total},
total =
Import["http://api..com/1.1/questions/" <>
ToString[questionID] <> "/answers?key=NgVJ4Y6vFkuF-oqI-eOvOw&pagesize=1", "JSON"];
If[total === $Failed, Return[$Failed], total = "total" /. total];
Join @@ Table[
"answer_id" /. ("answers" /.
Import["http://api..com/1.1/questions/" <>
ToString[questionID] <> "/answers?key=NgVJ4Y6vFkuF-oqI-eOvOw&pagesize=100&page=" <>
ToString[i], "JSON"]), {i, 1, Ceiling[total/100]}]
]
getAnswerIDsFromTag[tagName_String] :=
Module[{},
Join @@ (getAnswerIDsFromQuestionID /@
Cases[getQuestionIDs[tagName], Except[$Failed]])
]