Mikä olisi järkevin tapa analysoida seuraavan muotoista dataa? Kannattaisiko jopa laittaa ihan vaan Exceliin, vai onnistuisiko esim. PHP:llä helpommin.
Eli datassa on ensin päivämäärä, sitten aika, henkilön nimi ja kirjoittama viesti. Joskus henkilöllä voi olla pelkkä etunimi, joskus sekä etu- että sukunimi.
Alla katkelma datasta
7.2.2014 20.30.59: Erkki Esimerkki: Testiviesti 7.2.2014 20.30.59: Pekka: Myös moniriviset viestit mahdollisia 7.2.2014 20.30.59: Erkki Esimerkki: Testi
Jokainen viesti on siis eroteltu tyhjällä rivillä.
Tästä pitäisi saada poimittua esim. seuraavanlaisia tietoja
- tunneittain eroteltuna, paljonko viestejä on lähetetty (esim. klo 20 tietty määrä jne.)
- aktiivisin viestittelijä
- päivä jolloin on laitettu eniten viestejä
EDIT: Excelillä ei ainakaan onnistunut, nimittäin data on UTF8-muodossa.
lainaus:
- tunneittain eroteltuna, paljonko viestejä on lähetetty (esim. klo 20 tietty määrä jne.)
- aktiivisin viestittelijä
- päivä jolloin on laitettu eniten viestejä
Melko pienellä SQL-kyselyllä saat nuo. Miksi se pitäisi viedä exceliin vai onko syvempi analysointi tarkoituksena (luoda taullukkoja viestien lähetysajoista yms?)
p99o, mitenkä teet SQL-kyselyn tekstitiedostoon?
PHP:llä tekstin purkaminen onnistuu esim. säännöllisillä lausekkeilla melko helposti.
<?php $s = "tekstisi"; preg_match_all('`^(.*?): (.*?): (.*?)$(?:\\s+^\\s+^|\\Z)`sm', $s, $m); foreach ($m[0] as $i => $t) { $aika = $m[1][$i]; $nimi = $m[2][$i]; $viesti = $m[3][$i]; echo "Osuma $i: aika $aika, nimi $nimi, viesti $viesti\n"; }
Sitten vain muutat aikaleiman järkevään muotoon ja alat laskea.
Muuttaisin datan hieman standardimpaan muotoon esimerkiksi seuraavalla PHP-purkalla:
$data = explode("\n\n", file_get_contents($argv[1])); $f = fopen($argv[2], "w"); foreach ($data as $i) { $i = explode(": ", $i, 3); $i[0] = @date("Y-m-d H:i:s", @strtotime($i[0])); fputcsv($f, $i); }
CSV-muotoiseen dataan tekeekin helposti vaikka sen SQL-kyselyn.
$ php parsi_data.php viestit.txt viestit.csv $ sqlite3 -column -header -separator , :memory: sqlite> CREATE TABLE viestit(aika DATETIME, nimi TEXT, viesti TEXT); sqlite> .import viestit.csv viestit sqlite> SELECT nimi, COUNT(*) AS maara FROM viestit GROUP BY nimi ORDER BY maara DESC; nimi maara --------------- ---------- Erkki Esimerkki 2 Pekka 1
Kiitoksia vinkeistä. Vihdoin ehdin taas palata tähän asiaan. Aloin testailla tuota Metabolixin koodia. Ongelma on siinä, että teksti voi olla tällaistakin:
17.5.2014 0.25.44: Nimi: testiviesti testiviesti testi testitesti jatkuu tänne asti testi 17.5.2014 0.25.50: Nimi: testiä testiä
Eli yhdessä viestissä voi olla useitakin rivinvaihtoja. Tuossa yllä siis kaksi viestiä. Joten miten tuota säännöllistä lauseketta kannattaisi muuttaa, että se tunnistaisi jokaisen viestin alun paremmin?
Tee tarkempi lauseke viestin alulle ja lisää loppuun tarkistus, että seuraavaksi tulee joko tekstin loppu tai uusi viesti.
$re = '^(\\d+\\.\\d+\\.\\d+ \\d+\\.\\d+\\.\\d+): ([^:\\n]*):'; $re = "`{$re} (.*?)(?={$re}|\\Z)`sm"; preg_match_all($re, $s, $m);
Päivämäärän standardointi ja muutenkin datan muutto järkevämpään muotoon olisi järkevää.
Oletko miettinyt, mitä tapahtuu, jos käyttäjän viesti sisältää tuollaista samanlaista dataa? Esimerkiksi tässä olisi yksi Pekan viesti:
1.1.1111 1.11.11: Pekka: Lol kattokaa Jonnee! 2.2.2222 2.22.22: Jonne: spurdo spärde eiks oo läppä jäbä?
Koko viritelmä hajoaa, kun skripti ei pysty erottamaan viestin alkua ja viestin sisältöä.
Totta, tuossa on kyse WhatsAppin antamasta datasta, joka ei harmi kyllä noudata oikein mitään standardia. Tuo antamasi lauseke toimii hyvin, kiitos siitä. Ongelmaksi osottautui vain käyttämäni serverin rajallinen muistin määrä, dataa on kuitenkin 2,5Mt edestä.
Mistä saat tuota dataa? Luulisi, että WhatsApp antaa jossain järkevässä muodossa sitä.
Veikkaan että se on se WhatsAppin "backup"-tiedosto, joka on vain yksinkertainen tekstitiedosto.
Olli kirjoitti:
Ongelmaksi osottautui vain käyttämäni serverin rajallinen muistin määrä, dataa on kuitenkin 2,5Mt edestä.
Tiedoston koko ja muistin rajoitettu määrä eivät ole ongelmia. Sinun vain tarvitsee käyttää jotain järkevämpää menetelmää kuin Metabolixin tarjoama ad hoc -viritys. Lue tiedostoa rivi kerrallaan ja parsi viestit ulos yksitellen, jolloin muistia ei pala niin paljoa.
Olli kirjoitti:
Ongelmaksi osottautui vain käyttämäni serverin rajallinen muistin määrä, dataa on kuitenkin 2,5Mt edestä.
Voit hakea osumia yksitellen samaisella lausekkeella preg_match-funktiolla.
while (preg_match($re, $s, $m)) { // Poistetaan osuma tekstistä. $s = substr($s, strlen($m[0])); // Käsitellään osuma. $aika = $m[1]; // jne. }
Aihe on jo aika vanha, joten et voi enää vastata siihen.