2016-07-25 13 views
0

Ich werde beschreiben, was ich hier genauer im Detail meine. Angenommen, ich ein Datenblatt haben, die wie folgt aussieht: für Stackoverflow-FormatierungWie würde ich Zeilen basierend auf einem Wert in einer Spalte reduzieren?

+-----------+---------+---------+---------+---------+---------+---------+--------------+ 
|   | Person1 | Person2 | Person4 | Person4 | Person5 | Person6 |  City  | 
+-----------+---------+---------+---------+---------+---------+---------+--------------+ 
| January | -  |  - | Yes  |  - | Yes  | -  | SanFrancisco | 
| Febuary | Yes  |  - | -  |  - | -  | -  | SanFrancisco | 
| March  | -  |  - | -  |  - | -  | -  | SanFrancisco | 
| April  | -  |  - | -  |  - | -  | -  | NewYork  | 
| May  | Yes  |  - | -  |  - | -  | -  | NewYork  | 
| June  | -  |  - | -  |  - | -  | -  | NewYork  | 
| July  | -  |  - | -  |  - | Yes  | -  | NewYork  | 
| August | -  |  - | -  |  - | -  | -  | NewYork  | 
| September | -  |  - | -  |  - | -  | -  | Miami  | 
| November | -  |  - | -  |  - | -  | Yes  | Miami  | 
| December | -  |  - | -  |  - | -  | -  | Miami  | 
+-----------+---------+---------+---------+---------+---------+---------+--------------+ 

Ignorieren der ascii, Es ist eine einfache Tabelle, die 6 Personen verfolgt, basierend auf welcher Stadt sie waren in welchen Monaten.

Was ich nur wissen will ist, welche Leute welche Städte besucht haben. Effektiv die Liste kondensieren, um so zu sehen:

+---------+---------+---------+---------+---------+---------+--------------+ 
| Person1 | Person2 | Person4 | Person4 | Person5 | Person6 | City   | 
+---------+---------+---------+---------+---------+---------+--------------+ 
| Yes  | -  | Yes  | -  | Yes  | -  | SanFrancisco | 
| Yes  | -  | -  | -  | Yes  | -  | NewYork  | 
| -  | -  | -  | -  | -  | Yes  | Miami  | 
+---------+---------+---------+---------+---------+---------+--------------+ 

Jede Reihe ist nur EINE Stadt und enthält, welche Leute sie besucht haben. Gibt es einen optimalen Weg dies zu tun, oder eher, gibt es eine Art von tr (squeeze)/sed-Werkzeug, das dies bereits tut? Wenn ich das programmieren müsste, was wäre dann die optimale Logik?

+0

Sind die Zeilen 'Januar' und' SanFransisco' (zum Beispiel) konstant? Ich meine, kann eine Person in einer anderen Stadt im Januar oder nur in San Francisco sein? Zweitens, wie werden Ihre Daten dargestellt? Ist es ein Excel-Blatt? Eine Matrix? Eine 3D-Liste? –

+0

Sie sind nicht konstant, und ihre aktuelle Lage ist nicht bekannt .. es ist nur "berühmte Städte, die Sie besucht haben" in diesem Jahr. Die Liste ist eine einfache TSV oder CSV in einem Excel-Blatt. Ich plane, mit einem Python-Skript daran zu arbeiten. Die ASCII-Zeichen sind hier zur besseren Übersicht dargestellt, weil SO aus irgendeinem Grund keine Tabellen einfügen kann. – Tom

+0

Entschuldigung, dass ich das Problem nicht gut verstehe, aber was, wenn zum Beispiel Person 6 im Januar in Miami war? Wie wird es dargestellt? –

Antwort

1
$ cat tst.awk 
function prt() { 
    if (prev != "") { 
     for (i=2;i<=NF;i++) { 
      printf "%s%s", vals[i], (i<NF ? OFS : ORS) 
     } 
    } 
    delete vals 
} 

BEGIN { FS=OFS="," } 
$NF != prev { prt() } 
{ 
    for (i=1;i<=NF;i++) { 
     vals[i] = (vals[i] ~ /[[:alpha:]]/ ? vals[i] : $i) 
    } 
    prev = $NF 
} 
END { prt() } 

$ awk -f tst.awk file 
Person1,Person2,Person4,Person4,Person5,Person6,City 
Yes,-,Yes,-,Yes,-,SanFrancisco 
Yes,-,-,-,Yes,-,NewYork 
-,-,-,-,-,Yes,Miami 

Die obige übernimmt Ihre Eingabeformat ist wirklich eine CSV wie folgt aus:

$ cat file 
Month,Person1,Person2,Person4,Person4,Person5,Person6,City 
January,-,-,Yes,-,Yes,-,SanFrancisco 
Febuary,Yes,-,-,-,-,-,SanFrancisco 
March,-,-,-,-,-,-,SanFrancisco 
April,-,-,-,-,-,-,NewYork 
May,Yes,-,-,-,-,-,NewYork 
June,-,-,-,-,-,-,NewYork 
July,-,-,-,-,Yes,-,NewYork 
August,-,-,-,-,-,-,NewYork 
September,-,-,-,-,-,-,Miami 
November,-,-,-,-,-,Yes,Miami 
December,-,-,-,-,-,-,Miami 

und Sie wollen eine Ausgabe CSV.

+0

Ich scheine zu bekommen: Person1, Person2, Person4, Person4, person5, Person6, Stadt Ja - Ja, -, Ja, -, SanFrancisco Ja, -, -, -, Ja, -, NewYork -, -, -, -, -, Ja, Miami -, -, -, -, -, -, Miami (mit Miami zweimal wiederholt) – Tom

+0

@ Tom dann bist du nicht aktiv das Skript, das ich in die von mir gepostete Eingabedatei geschrieben habe. Vielleicht haben Sie eine leere Zeile am Ende Ihrer Datei? Vielleicht enthält es Control-Ms ('cat -v file' zu ​​überprüfen)? Bearbeiten Sie Ihre Frage, um den Befehl, den Sie ausführen, die Eingabedatei, für die Sie sie ausführen, und die Ausgabe, die Sie erhalten, anzuzeigen, wenn Sie weitere Hilfe benötigen. –

2

Der richtige Ausdruck für das, was Sie hier versuchen, ist Aggregation. Das Wort Kollaps wird in meiner Erfahrung nicht allgemein für diese Operation verwendet.

Ich bin Art von Python Lernen on-the-fly hier, so könnte es einen besseren Weg, aber ich habe diese, insbesondere die DataFrame Typ mit dem pandas Modul zu arbeiten bekommen:

import pandas; 
import re; 

df = pandas.DataFrame({ 
    'Date':['January','Febuary','March','April','May','June','July','August','September','November','December'], 
    'Person1':['-','Yes','-','-','Yes','-','-','-','-','-','-'], 
    'Person2':['-','-','-','-','-','-','-','-','-','-','-'], 
    'Person3':['Yes','-','-','-','-','-','-','-','-','-','-'], 
    'Person4':['-','-','-','-','-','-','-','-','-','-','-'], 
    'Person5':['Yes','-','-','-','-','-','Yes','-','-','-','-'], 
    'Person6':['-','-','-','-','-','-','-','-','-','Yes','-'], 
    'City':['SanFrancisco','SanFrancisco','SanFrancisco','NewYork','NewYork','NewYork','NewYork','NewYork','Miami','Miami','Miami'] 
}); 

df.groupby('City').agg({k:lambda x: 'Yes' if 'Yes' in x.values else '-' for k in filter(lambda x:re.search(r'^Person',x),df.keys())}); 
##    Person2 Person3 Person1 Person6 Person4 Person5 
## City 
## Miami    -  -  -  Yes  -  - 
## NewYork   -  -  Yes  -  -  Yes 
## SanFrancisco  -  Yes  Yes  -  -  Yes 

Auch würde ich empfehlen, in die R programming language, die eine ausgezeichnete und zunehmend allgegenwärtige Statistik, Grafiken und allgemeine Datenanalyse-Plattform, die perfekt für die Arbeit mit Excel-Stil tabellarische Daten ist. Diese Art von Datenformattransformationen sind in R auf jeden Fall natürlicher, obwohl die Lernkurve ziemlich steil ist. Hier ist die R Implementierung:

df <- read.csv(stringsAsFactors=F,text= 
'Date,Person1,Person2,Person3,Person4,Person5,Person6,City 
January,-,-,Yes,-,Yes,-,SanFrancisco 
Febuary,Yes,-,-,-,-,-,SanFrancisco 
March,-,-,-,-,-,-,SanFrancisco 
April,-,-,-,-,-,-,NewYork 
May,Yes,-,-,-,-,-,NewYork 
June,-,-,-,-,-,-,NewYork 
July,-,-,-,-,Yes,-,NewYork 
August,-,-,-,-,-,-,NewYork 
September,-,-,-,-,-,-,Miami 
November,-,-,-,-,-,Yes,Miami 
December,-,-,-,-,-,-,Miami' 
); 

aggregate(.~City,df[-1L],function(x) if (any(x=='Yes')) 'Yes' else '-'); 
##   City Person1 Person2 Person3 Person4 Person5 Person6 
## 1  Miami  -  -  -  -  -  Yes 
## 2  NewYork  Yes  -  -  -  Yes  - 
## 3 SanFrancisco  Yes  -  Yes  -  Yes  - 
+0

"Aggregat". Ich werde mich daran erinnern. Vielen Dank! – Tom