Skip to content

Commit 3ef43b0

Browse files
committed
Fix categorical "" treatment in long_to_wide
Previously, "" wouldn't be found in a categorical because of Pandas bug pandas-dev/pandas#36550 [finishes #174929289] Tests and code have been updated to conform to Pandas 1.1 reshape behavior, which reshapes Categorical to Categorical. This should be backwards-compatible with Pandas 0.25 on production.
1 parent 1c68537 commit 3ef43b0

File tree

5 files changed

+42
-40
lines changed

5 files changed

+42
-40
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
2020-09-22.01
22
-------------
33

4+
* long-to-wide: fix to handle Var="" rows when the Var column is
5+
compressed as "Categorical". Previously, an error occurred.
6+
7+
2020-09-22.01
8+
-------------
9+
410
* long-to-wide: fix to correctly ignore (Key=xyz, Var=NULL) rows when
511
there is no (Key=xyz, Var=not-null) row the Key column is compressed
612
as "Categorical". Previously, an error occurred.

locale/el/messages.po

+6-29
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ msgid ""
88
msgstr ""
99
"Project-Id-Version: PROJECT VERSION\n"
1010
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
11-
"POT-Creation-Date: 2020-09-22 14:58+0000\n"
11+
"POT-Creation-Date: 2020-09-22 15:46+0000\n"
1212
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414
"Language: el\n"
@@ -63,79 +63,56 @@ msgstr ""
6363
#: reshape.py:67
6464
msgid "wide_to_long.badColumns.mixedTypes.message"
6565
msgstr ""
66-
"Έγινε αυτόματη μετατροπή {n_columns, plural, other{# στηλών (δείτε "
67-
"\"{first_colname}\")} one {της στήλης \"{first_colname}\"}} σε κείμενο "
68-
"επειδή η στήλη τιμής δεν μπορεί να έχει διαφορετικούς τύπους."
6966

7067
#: reshape.py:74
7168
msgid "wide_to_long.badColumns.mixedTypes.quick_fix.text"
72-
msgstr "Μετατροπή {n_columns, plural, one {# στήλης} other {# στηλών}} σε κείμενο"
69+
msgstr ""
7370

7471
#: reshape.py:106
7572
msgid "long_to_wide.badColumn.notText.message"
7673
msgstr ""
77-
"Έγινε αυτόματη μετατροπή της στήλης \"{column_name}\" σε κείμενο επειδή "
78-
"τα ονόματα στηλών πρέπει να είναι κείμενο."
7974

8075
#: reshape.py:114
8176
msgid "long_to_wide.badColumn.notText.quick_fix.text"
82-
msgstr "Μετατροπή της στήλης \"{column_name}\" σε κείμενο"
77+
msgstr ""
8378

8479
#: reshape.py:136
8580
msgid "long_to_wide.badRows.emptyColumnHeaders.warning"
8681
msgstr ""
87-
"{n_rows, plural, one {# σειρά με κενή στήλη \"{column_name}\" "
88-
"αφαιρέθηκε.} other {# σειρές με κενή στήλη \"{column_name}\" "
89-
"αφαιρέθηκαν.}}"
9082

9183
#: reshape.py:150
92-
#, fuzzy
9384
msgid "long_to_wide.error.repeatedVariables"
94-
msgstr "Δεν είναι δυνατή η αναδιαμόρφωση: μερικές μεταβλητές επαναλαμβάνονται"
85+
msgstr ""
9586

9687
#: reshape.py:156
9788
msgid "long_to_wide.error.noValueColumn"
9889
msgstr ""
99-
"Δεν υπάρχει στήλη τιμής. Όλες οι στήλες του πίνακα εκτός από μία πρέπει "
100-
"να είναι μεταβλητή σειράς ή στήλης."
10190

10291
#: reshape.py:162
10392
msgid "long_to_wide.error.tooManyValueColumns"
10493
msgstr ""
105-
"Υπάρχουν πολλές στήλες τιμής. Όλες οι στήλες του πίνακα εκτός από μία "
106-
"πρέπει να είναι μεταβλητή σειράς ή στήλης. Αφαιρέστε τις επιπλέον στήλες "
107-
"πριν από την αναδιαμόρφωση."
10894

10995
#: reshape.py:209
11096
msgid "error.sameColumnAndRowVariables"
11197
msgstr ""
112-
"Δεν είναι δυνατή η αναδιαμόρφωση: οι μεταβλητές στηλών και σειρών πρέπει "
113-
"να είναι διαφορετικές"
11498

11599
#: reshape.py:330
116100
msgid "transpose.warnings.tooManyRows"
117101
msgstr ""
118-
"Περικόψαμε την είσοδο σε {max_columns} σειρές έτσι ώστε ο "
119-
"αντιμετατιθέμενος πίνακας να έχει λογικό αριθμό στηλών."
120102

121103
#: reshape.py:349
122104
msgid "transpose.warnings.headersConvertedToText.message"
123105
msgstr ""
124-
"Έγινε αυτόματη μετατροπή των κεφαλίδων στη στήλη \"{column_name}\" σε "
125-
"κείμενο."
126106

127107
#: reshape.py:356
128108
msgid "transpose.warnings.headersConvertedToText.quickFix.text"
129-
msgstr "Μετατροπή της στήλης {column_name} σε κείμενο"
109+
msgstr ""
130110

131111
#: reshape.py:394
132112
msgid "transpose.warnings.differentColumnTypes.message"
133113
msgstr ""
134-
"Έγινε αυτόματη μετατροπή {n_columns, plural, other {# στηλών (δείτε "
135-
"\"{first_colname}\")} one {της στήλης \"{first_colname}\"}} σε κείμενο "
136-
"επειδή όλες οι στήλες πρέπει να ανήκουν στον ίδιο τύπο."
137114

138115
#: reshape.py:401
139116
msgid "transpose.warnings.differentColumnTypes.quickFix.text"
140-
msgstr "Μετατροπή {n_columns, plural, other {# στηλών} one {# στήλης}} σε κείμενο"
117+
msgstr ""
141118

locale/en/messages.po

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ msgid ""
88
msgstr ""
99
"Project-Id-Version: PROJECT VERSION\n"
1010
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
11-
"POT-Creation-Date: 2020-09-22 14:58+0000\n"
11+
"POT-Creation-Date: 2020-09-22 15:46+0000\n"
1212
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414
"Language: en\n"

reshape.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def long_to_wide(
129129

130130
# Remove empty values, in-place. Empty column headers aren't allowed.
131131
# https://www.pivotaltracker.com/story/show/162648330
132-
empty = varcol.isin([np.nan, pd.NaT, None, ""])
132+
empty = varcol.isin([np.nan, None, ""])
133133
n_empty = np.count_nonzero(empty)
134134
if n_empty:
135135
warnings.append(
@@ -169,11 +169,11 @@ def long_to_wide(
169169
table = table.unstack()
170170
table.columns = [col[-1] for col in table.columns.values]
171171
table.reset_index(inplace=True)
172-
for key_colname in key_colnames:
173-
key_series = table[key_colname]
174-
if hasattr(key_series, "cat"):
172+
for colname in list(table.columns):
173+
series = table[colname]
174+
if hasattr(series, "cat"):
175175
# Remove unused categories
176-
key_series.cat.remove_unused_categories(inplace=True)
176+
series.cat.remove_unused_categories(inplace=True)
177177

178178
if warnings:
179179
return (table, warnings)

test_reshape.py

+24-5
Original file line numberDiff line numberDiff line change
@@ -151,17 +151,20 @@ def test_long_to_wide_categoricals(self):
151151
pd.DataFrame(
152152
{
153153
"x": pd.Series(["1", "2", "3"], dtype="category"),
154-
"A": ["a", "b", "c"],
155-
"B": ["d", "e", "f"],
154+
"A": pd.Series(["a", "b", "c"], dtype="category"),
155+
"B": pd.Series(["d", "e", "f"], dtype="category"),
156156
}
157157
),
158158
)
159159

160160
def test_long_to_wide_nix_unused_category(self):
161161
# https://www.pivotaltracker.com/story/show/174929299
162162
in_table = pd.DataFrame(
163-
{"A": list("aab"), "B": [None, None, "c"], "value": list("abc")},
164-
dtype="category",
163+
{
164+
"A": list("aab"),
165+
"B": pd.Series([None, None, "c"], dtype="category"),
166+
"value": list("abc"),
167+
},
165168
)
166169
out = render(
167170
in_table, P("longtowide", ["A"], ltw_varcolname="B"), **DefaultKwargs
@@ -170,14 +173,30 @@ def test_long_to_wide_nix_unused_category(self):
170173
out[0],
171174
pd.DataFrame(
172175
{
173-
"A": pd.Series(["b"], dtype="category"),
176+
"A": ["b"],
174177
"c": ["c"],
175178
}
176179
),
177180
)
178181
# There's also a long_to_wide.badRows.emptyColumnHeaders.warning, but that's
179182
# not under test here
180183

184+
def test_long_to_wide_treat_empty_string_category_as_empty_string(self):
185+
# https://www.pivotaltracker.com/story/show/174929289
186+
in_table = pd.DataFrame(
187+
{
188+
"A": ["a", "b"],
189+
"B": pd.Series(["", ""], dtype="category"),
190+
"C": [1, 2],
191+
}
192+
)
193+
out = render(
194+
in_table, P("longtowide", ["A"], ltw_varcolname="B"), **DefaultKwargs
195+
)
196+
assert_frame_equal(out[0], pd.DataFrame({"A": pd.Series([], dtype=object)}))
197+
# there's also a long_to_wide.badRows.emptyColumnHeaders.warning, but that's
198+
# not under test here
199+
181200
def test_long_to_wide_missing_varcol(self):
182201
out = render(
183202
pd.DataFrame({"A": [1, 2]}),

0 commit comments

Comments
 (0)