提问人:Diego H 提问时间:11/14/2023 最后编辑:Diego H 更新时间:11/21/2023 访问量:61
如何读取带有熊猫坏行的 CSV 的最后 n 列?
How can I read the last n columns of a CSV with bad lines with pandas?
问:
我在尝试使用 pandas 读取 CSV 文件时遇到了一个问题。CSV 结构如下:
Col1, Col2, Col3, Col4, Col5
a1, a2, a3, a4, a5
b1, b2, b3, b4, b5
c1, c3, c4, c5
d1, d2, d3, d4, d5
有些行包含缺失值,我特别想只提取每行的最后一个单元格,因为这些单元格是肯定存在的。在给定的示例中,其中 ,所需的 DataFrame 应如下所示:n
n=3
Col3 Col4 Col5
0 a3 a4 a5
1 b3 b4 b5
2 c3 c4 c5
3 d3 d4 d5
我尝试使用 usecols=[2, 3, 4],但它导致了 N/A 值:
Col3 Col4 Col5
0 a3 a4 a5
1 b3 b4 b5
2 c4 c5 NaN
3 d3 d4 d5
关于如何实现预期结果的任何指导将不胜感激。感谢您的帮助!
答:
很难直接在read_csv
层面处理这个问题。一个选项可能是加载所有数据,然后重新对齐它:
df = pd.read_csv(data)
mask = df.notna().loc[:, ::-1].cummax(axis=1).loc[:, ::-1]
out = pd.DataFrame(df.to_numpy()[np.arange(len(df))[:,None],
np.argsort(mask)],
index=df.index, columns=df.columns
)
输出:
Col1 Col2 Col3 Col4
a1 a2 a3 a4 a5
b1 b2 b3 b4 b5
c1 NaN c3 c4 c5
d1 d2 d3 d4 d5
然后,您可以仅选择所需的列
如果您只想处理最后几列:n
last_col = 3
mask = df.notna().iloc[:, :-last_col-1:-1].cummax(axis=1).iloc[:, ::-1]
out = df.copy()
out.iloc[:, -last_col:] = (df
.iloc[:, -last_col:]
.to_numpy()[np.arange(len(df))[:,None],
np.argsort(mask)])
输出:
Col1 Col2 Col3 Col4
a1 a2 a3 a4 a5
b1 b2 b3 b4 b5
c1 c3 NaN c4 c5
d1 d2 d3 d4 d5
为了好玩,您可以尝试使用正则表达式分隔符:
N = 3 # last N columns
pat = r".+?{}?$".format("([^,]+),"*N)
df = pd.read_csv(file, sep=pat, engine="python").dropna(how="all", axis=1)
输出:
print(df)
Col2 Col3 Col4
0 a3 a4 a5
1 b3 b4 b5
2 c3 c4 c5
3 d3 d4 d5
评论
如果您只想提取每行最后一个单元格的值,则可以使用以下代码获取每行的最后一个单元格。
法典:
import pandas as pd
from io import StringIO
csv_data = """
Col1, Col2, Col3, Col4
a1, a2, a3, a4, a5
b1, b2, b3, b4, b5
c1, c3, c4, c5
d1, d2, d3, d4, d5
"""
df = pd.read_csv(StringIO(csv_data))
last_values = df.apply(lambda row: row.dropna().iloc[-1] if not row.dropna().empty else pd.NA, axis=1)
for _, value in zip(last_values.index, last_values):
print(value)
“df = pd.read_csv(StringIO(csv_data))” 此行使用 pd.read_csv 函数将 CSV 数据读入 Pandas DataFrame (df)。StringIO(csv_data) 用于将字符串csv_data转换为pd.read_csv可以读取的类似文件的对象。
“last_values = df.apply(lambda row: row.dropna().iloc[-1] if not row.dropna().empty else pd.NA, 轴=1)” 在这里,通过将 lambda 函数应用于 DataFrame (df) 的每一行,创建了一个名为 last_values 的新 Series。lambda 函数使用 row.dropna() 检查该行是否具有任何非 null 值。如果它不为空,则使用 iloc[-1] 提取最后一个非 null 值。如果该行为空,则分配 pd。NA(Pandas 对缺失值的表示)。
" 对于 _,zip(last_values.index, last_values) 中的值: print(值) " 最后,循环遍历 last_values 系列的索引和值,并打印每个值。此循环实质上是打印原始 DataFrame 每行中的最后一个非 null 值。
如果 pandas 不是必需的,我想我会使用 CSV 包和默认阅读器来挑选每行的最后三列:
像这样:
import io
import csv
data = """
Col1,Col2,Col3,Col4
a1,a2,a3,a4,a5
b1,b2,b3,b4,b5
c1,c3,c4,c5
d1,d2,d3,d4,d5
""".strip()
with io.StringIO(data) as file_in:
reader = csv.reader(file_in)
headers = next(reader) # not sure if you want/nead the header
rows = [row[-3:] for row in reader] # the last three columns
现在你可以做你喜欢的事情了rows
for row in rows:
print(row)
会给你:
['a3', 'a4', 'a5']
['b3', 'b4', 'b5']
['c3', 'c4', 'c5']
['d3', 'd4', 'd5']
评论
c2
open()
read()
DataFrame
c2
c5
c1, , c3, , c5
n=3
Col5