首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >获取熊猫数据栏的长度而不带头

获取熊猫数据栏的长度而不带头
EN

Stack Overflow用户
提问于 2019-09-06 18:29:18
回答 2查看 5.3K关注 0票数 1

我有个新手的问题!

我有一个熊猫数据文件,源是一个逗号分隔的csv文件。文件没有头文件。

对于每一行,我需要知道列的len是什么,然后我需要删除那些具有len优于某些值的行,例如5。

我所拥有的:

1,2,3,4,5,6

1,2,3

9,6,8

1,2,3,5,6

期望产出:

1,2,3

9,6,8

我搜索了一些问题和答案,比如:

Delete rows from a pandas DataFrame based on a conditional expression involving len(string) giving KeyError

Select row using the length of list in pandas cell

How to remove a row from pandas dataframe based on the length of the column values?

但据我所知,它总是使用某个列名来执行过滤器,而且由于文件中没有标题,而且列的数量从一个行到另一个行,我不知道如何实现。

你能帮忙吗?

提前感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-09-06 21:26:53

我看到了三种可能性。

  1. 读取该文件两次(第一次是数数字段,第二次是将其读入熊猫中,使用跳过头的方法)
  2. 将其读入内存,过滤掉无效行,然后使用StringIO将其传递给熊猫。
  3. 将其读入所有列(或num所需列+ 1)的熊猫中,然后只允许多列包含NaN的行

下面的示例使用变量len_threshold (应该设置为一行允许的列数)和your_file_name (应该包含csv文本文件的名称)。

方法1:读取文件两次

为了方便,你可以用熊猫做这个。如下所示:

代码语言:javascript
运行
复制
# read the rows into one text column
df= pd.read_csv(your_file_name, names=['text'], sep='\n')
# count the separators
counts= df['text'].str.count(',')
# now all rows which have more or less than two separators are skipped
rows_to_skip= counts[counts > len_threshold].index.get_level_values(0).to_list()
pd.read_csv(your_file_name, names=list(range(len_threshold)), index_col=False, skiprows=rows_to_skip)

注意,要应用此方法,您应该确保您的字段不包含分隔符,因为它不检查逗号是否在引用的文本中。

方法2:记忆/变体:逐行阅读熊猫

代码语言:javascript
运行
复制
string_buffer= io.StringIO()
with open(your_file_name, 'rt') as fp:
    at_end= False
    i=0
    while not at_end:
        line= fp.readline()
        if line == '':
            break
        elif line.count(',') <= len_threshold:
            string_buffer.write(line)
# "rewind" the string_buffer in order to read it from it's start
string_buffer.seek(0)
df= pd.read_csv(string_buffer, names=list(range(len_threshold)), index_col=False)

注意,如上所述,要应用此方法,您应该确保您的字段不包含分隔符,因为它不检查逗号是否在引用的文本中。它需要更多的内存,因此不适用于非常大的文件。但是,您也可以使用这种方法的一个变体,而不是将正确的行写入字符串缓冲区,而是使用read_csv将它们读入熊猫体内。这样,你也不需要担心类型转换,但熊猫可能会遇到问题,在猜类型的权利,只要看一栏。但是,如果您已经知道理想的列类型,当然可以传递它们。该变体如下所示:

代码语言:javascript
运行
复制
df= pd.DataFrame([], columns=range(len_threshold))
df_len=0
string_buffer= io.StringIO()
with open(your_file_name, 'rt') as fp:
    at_end= False
    i=0
    while not at_end:
        line= fp.readline()
        if line == '':
            break
        elif line.count(',') <= len_threshold:
            tmp_df= pd.read_csv(io.StringIO(line), names=range(len_threshold), index_col=False)
            df.loc[df_len]= tmp_df.iloc[0]
            df_len+= 1

方法3:读取数据帧,然后过滤掉不正确的行

这是最简单的方法。

代码语言:javascript
运行
复制
# read the whole dataframe with all columns
df= pd.read_csv(your_file_name, header=None, index_col=False)
# define an indexer that considers all rows to be good which
# have nothing else in the access rows as `NaN`
if len(df.columns) > len_threshold:
    good_rows= df.iloc[:, len_threshold:].isna().all(axis='columns')
    df.drop(df[~good_rows].index.get_level_values(0), inplace=True)
    df.drop(df.columns[3:], axis='columns', inplace=True)

因此,只要字段为空,此方法也可能允许行具有多余的字段分隔符。在上面的版本中,它还允许行少于3列。例如,如果第三列总是在有效行中包含某些内容,则很容易排除太短的行。只需将"good_rows“行更改为:

代码语言:javascript
运行
复制
    good_rows= df.iloc[:, len_threshold:].isna().all(axis='columns') & ~df.iloc[:, 2].isna()
票数 1
EN

Stack Overflow用户

发布于 2019-09-06 20:47:47

如果将参数header=None传递给pandas.read_csv(),则列名是从0索引的整数。因此,如果您有以下"file.csv":

代码语言:javascript
运行
复制
1,2,3,4,5,6
1,2,3
9,6,8
1,2,3,5,6

您可以使用以下代码将其读入DataFrame中:

代码语言:javascript
运行
复制
import pandas as pd

df = pd.read_csv("file.csv", header=None, dtype="Int64")

如果要执行print(df),您的结果将是:

代码语言:javascript
运行
复制
   0  1  2    3    4    5
0  1  2  3    4    5    6
1  1  2  3  NaN  NaN  NaN
2  9  6  8  NaN  NaN  NaN
3  1  2  3    5    6  NaN

现在,如果您想删除所有大于或等于五个非NaN值的行,下面的代码应该可以做到这一点:

代码语言:javascript
运行
复制
for index, row in df.iterrows():
    if sum(row.notnull()) >= 5:
        df.drop(index, inplace=True)

df.dropna(axis=1, how="all", inplace=True)

如果要执行print(df),新的结果将是:

代码语言:javascript
运行
复制
   0  1  2
1  1  2  3
2  9  6  8

现在,如果您想要覆盖删除较长的行的file.csv,那么它就很简单了:

代码语言:javascript
运行
复制
df.to_csv("file.csv", header=False, index=False)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57826988

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档